# ProxyM Dashboard API Reference

Complete REST API documentation for the ProxyM Dashboard.

## Base URL

```
http://localhost:4001/dashboard
```

## Authentication

Currently, the dashboard API does not require authentication. This is intended for local development use.

---

## Tools API

### List All Tools

```
GET /dashboard/tools/
```

Returns all registered development tools with their configuration and availability status.

**Query Parameters:**
- `category` (optional) - Filter by category: `ide`, `agent_cli`, `browser`, `human`
- `available_only` (optional) - Only show available tools: `true` or `false`

**Response:**
```json
{
  "tools": [
    {
      "name": "aider",
      "category": "agent_cli",
      "binary": "aider",
      "available": true,
      "capabilities": ["code_edit", "refactor", "test_run", "chat"],
      "modes": ["code", "architect", "ask"],
      "default_model": "smart",
      "default_instance": "host",
      "instances": [
        {
          "name": "host",
          "kind": "host",
          "command": ["aider"],
          "available": true,
          "description": "Run the aider CLI directly on the host."
        },
        {
          "name": "docker",
          "kind": "docker",
          "service": "aider",
          "profile": "tools",
          "container_name": "proxym-aider",
          "available": true
        }
      ],
      "description": "AI pair programming in the terminal"
    }
  ],
  "count": 9
}
```

### Get Tool Summary

```
GET /dashboard/tools/summary
```

Returns a summary of tool availability counts.

**Response:**
```json
{
  "total": 9,
  "available": 7,
  "tools": [...]
}
```

### Get Specific Tool

```
GET /dashboard/tools/{tool_name}
```

Returns details for a specific tool.

**Example:**
```bash
curl http://localhost:4001/dashboard/tools/aider
```

### Tool Health Check

```
GET /dashboard/tools/healthcheck
```

Comprehensive health check for every registered tool. Includes binary availability, provider configuration, Docker/KVM/VM instance status, and actionable fixes.

**Response:**
```json
{
  "tools": [
    {
      "name": "aider",
      "category": "agent_cli",
      "available": true,
      "binary_found": true,
      "docker_instance": false,
      "kvm_instance": false,
      "vm_instance": false,
      "provider": "openrouter",
      "provider_configured": true,
      "api_key_present": true,
      "status": "ok",
      "issues": [],
      "fixes": []
    },
    {
      "name": "vscode",
      "category": "ide",
      "available": false,
      "binary_found": false,
      "docker_instance": false,
      "status": "unavailable",
      "issues": ["Docker-backed VS Code container not running"],
      "fixes": [
        {
          "action": "start_container",
          "label": "Start VS Code container",
          "command": "docker compose --profile vscode up -d",
          "description": "Start the VS Code Web container"
        }
      ]
    }
  ],
  "summary": {
    "total": 9,
    "ok": 5,
    "degraded": 2,
    "unavailable": 2
  },
  "providers_configured": ["openrouter", "ollama"],
  "tool_providers": {
    "aider": "openrouter",
    "claude-code": "openrouter"
  }
}
```

**Status Values:**
- `ok` - Tool is fully operational
- `degraded` - Tool works but has issues (e.g., no binary but provider available)
- `unavailable` - Tool cannot be used

**Fix Actions:**
- `install` - Install missing binary
- `start_container` - Start Docker container
- `start_vm` - Start KVM/VM virtual machine
- `config` - Requires configuration (API key)
- `info` - Requires manual action (desktop IDE)

---

## Tool Dispatch

### Dispatch Tool to Ticket

```
POST /dashboard/tools/dispatch
```

Dispatches a tool to work on a ticket. Enqueues a job (except for `human` tool which bypasses executor).

**Request Body:**
```json
{
  "ticket_id": "TKT-000001",
  "tool": "aider",
  "mode": "code",
  "model": "smart",
  "project_dir": "/home/user/projects/myapp"
}
```

**Fields:**
- `ticket_id` (required) - Ticket ID to dispatch
- `tool` (required) - Tool name: `aider`, `claude-code`, `windsurf`, `cursor`, `vscode`, `roo-code`, `cline`, `browser`, `human`
- `mode` (optional) - Agent mode: `code`, `architect`, `debug`, `ask`
- `model` (optional) - Model alias or full name
- `project_dir` (optional) - Override project directory

**Response:**
```json
{
  "job": {
    "job_id": "JOB-abc123",
    "ticket_id": "TKT-000001",
    "tool_name": "aider",
    "status": "queued",
    "created_at": "2025-03-23T14:30:00Z"
  },
  "message": "Job JOB-abc123 enqueued for aider"
}
```

**Human Tool Special Behavior:**
When dispatching `human` tool, no job is created. Instead, the ticket is directly assigned:
```json
{
  "job": null,
  "ticket": { ... },
  "message": "Human task assigned for ticket TKT-000001"
}
```

---

## Job Queue API

### Queue Status

```
GET /dashboard/tools/queue
```

Returns queue summary and recent jobs.

**Response:**
```json
{
  "total": 5,
  "queued": 2,
  "running": 1,
  "done": 1,
  "failed": 1,
  "cancelled": 0,
  "recent_jobs": [
    {
      "job_id": "JOB-abc123",
      "ticket_id": "TKT-000001",
      "tool_name": "aider",
      "status": "running",
      "model": "openrouter/anthropic/claude-sonnet-4",
      "project_dir": "/home/user/projects/myapp",
      "prompt_length": 1500,
      "prompt_excerpt": "Add user authentication...",
      "created_at": "2025-03-23T14:30:00Z",
      "started_at": "2025-03-23T14:30:05Z"
    }
  ]
}
```

### List Jobs

```
GET /dashboard/tools/queue/jobs
```

List jobs with optional status filter.

**Query Parameters:**
- `status` (optional) - Filter by: `queued`, `running`, `done`, `failed`, `cancelled`
- `limit` (optional) - Max results: 1-200 (default: 50)

### Get Job Details

```
GET /dashboard/tools/queue/jobs/{job_id}
```

Returns detailed job information including logs and execution metadata.

**Response:**
```json
{
  "job_id": "JOB-abc123",
  "ticket_id": "TKT-000001",
  "tool_name": "aider",
  "status": "done",
  "model": "openrouter/anthropic/claude-sonnet-4",
  "project_dir": "/home/user/projects/myapp",
  "prompt_length": 1500,
  "prompt_excerpt": "Add user authentication to the API...",
  "created_at": "2025-03-23T14:30:00Z",
  "started_at": "2025-03-23T14:30:05Z",
  "completed_at": "2025-03-23T14:32:30Z",
  "result": {
    "success": true,
    "exit_code": 0,
    "stdout": "Modified 2 files...",
    "stderr": "",
    "stdout_lines": ["Modified src/auth.py", "Modified tests/test_auth.py"],
    "stderr_lines": [],
    "execution_metadata": {
      "model": "openrouter/gemini/gemini-3-flash-preview",
      "provider": "openrouter",
      "tokens_used": 2500,
      "duration_seconds": 145.5
    }
  },
  "ticket": {
    "id": "TKT-000001",
    "task": "Add authentication",
    "status": "in_progress"
  }
}
```

### Cancel Job

```
POST /dashboard/tools/queue/jobs/{job_id}/cancel
```

Cancels a queued job. Cannot cancel running jobs.

### Retry Job

```
POST /dashboard/tools/queue/jobs/{job_id}/retry
```

Retries a failed or cancelled job with the same parameters.

### Repair Job

```
POST /dashboard/tools/queue/jobs/{job_id}/repair
```

Runs auto-diagnosis on a failed job and suggests fixes.

**Response:**
```json
{
  "diagnosis": "The tool binary was not found on PATH",
  "suggestion": "Install aider using pip",
  "quick_fixes": [
    {
      "action": "install",
      "label": "Install aider",
      "command": "pip install aider-chat",
      "description": "Install the aider Python package"
    }
  ],
  "job_id": "JOB-abc123",
  "tool": "aider",
  "job_error": "aider: not found on PATH"
}
```

---

## Auto-Fix API

### Execute Auto-Fix

```
POST /dashboard/tools/autofix
```

Execute an automatic fix for a tool issue.

**Request Body:**
```json
{
  "tool_name": "aider",
  "fix_action": "install",
  "command": "pip install aider-chat"
}
```

**Fix Actions:**
- `install` - Execute installation command
- `start_container` - Start Docker container
- `start_vm` - Start KVM VM (via virsh)
- `info` or `config` - Creates human ticket (requires manual action)

**Response:**
```json
{
  "tool": "aider",
  "action": "install",
  "executed": true,
  "output": "Successfully installed aider-chat...",
  "error": "",
  "exit_code": 0,
  "ticket_created": null
}
```

**For Human Action (info/config):**
```json
{
  "tool": "windsurf",
  "action": "info",
  "executed": false,
  "output": "",
  "error": "Fix requires human action. Ticket created: TKT-000042",
  "ticket_created": {
    "id": "TKT-000042",
    "task": "Manual setup required: windsurf",
    "status": "backlog"
  }
}
```

### Bulk Auto-Fix

```
POST /dashboard/tools/autofix/bulk
```

Run auto-fix for all degraded tools that support automatic fixes.

**Response:**
```json
{
  "executed": 2,
  "failed": 1,
  "human_required": 3,
  "results": [
    {
      "tool": "vscode",
      "fix": "Start VS Code container",
      "result": {
        "executed": true,
        "output": "Container started successfully"
      }
    },
    {
      "tool": "windsurf",
      "fix": "Install windsurf",
      "ticket_created": "TKT-000043"
    }
  ]
}
```

---

## Tool Provider API

### Get Tool Providers

```
GET /dashboard/tools/providers
```

Returns current tool → provider mappings.

**Response:**
```json
{
  "tool_providers": {
    "aider": "openrouter",
    "claude-code": "openrouter",
    "browser": "openrouter"
  },
  "available_providers": ["openrouter", "ollama", "anthropic"]
}
```

### Set Tool Provider

```
POST /dashboard/tools/provider
```

Assign an LLM provider to a specific tool.

**Request Body:**
```json
{
  "tool": "aider",
  "provider": "ollama"
}
```

**Available Providers:**
- `openrouter` - OpenRouter.ai (default)
- `anthropic` - Anthropic API
- `openai` - OpenAI API
- `ollama` - Local Ollama instance
- `manual` - For human tool

---

## Tickets API

### List Tickets

```
GET /dashboard/tickets
```

Returns all tickets with optional filtering.

**Query Parameters:**
- `project_id` (optional) - Filter by project
- `status` (optional) - Filter by status: `backlog`, `todo`, `in_progress`, `in_review`, `done`, `cancelled`
- `sprint_id` (optional) - Filter by sprint
- `assigned_to` (optional) - Filter by assigned user
- `tag` (optional) - Filter by tag

### Create Ticket

```
POST /dashboard/tickets
```

Creates a new ticket.

**Request Body:**
```json
{
  "task": "Implement user authentication",
  "description": "Add JWT-based auth to API endpoints",
  "project_id": "proj-myapp",
  "priority": "high",
  "type": "task",
  "tags": ["backend", "security"],
  "estimated_hours": 4
}
```

**Priority Values:** `low`, `medium`, `high`, `critical`

**Type Values:** `task`, `bug`, `feature`, `epic`, `research`

### Get Ticket Detail

```
GET /dashboard/tickets/{ticket_id}
```

Returns detailed ticket information including job history.

**Response:**
```json
{
  "id": "TKT-000001",
  "task": "Implement user authentication",
  "title": "User Authentication",
  "project_id": "proj-myapp",
  "description": "Add JWT-based auth...",
  "status": "in_progress",
  "priority": "high",
  "type": "task",
  "assigned_tool": {
    "tool": "aider",
    "agent_mode": "code",
    "model": "smart"
  },
  "last_job": {
    "job_id": "JOB-abc123",
    "status": "done",
    "tool_name": "aider",
    "model": "openrouter/anthropic/claude-sonnet-4",
    "project_dir": "/home/user/projects/myapp",
    "prompt_length": 1500,
    "prompt_excerpt": "Add user authentication...",
    "success": true,
    "exit_code": 0,
    "stdout_lines": ["Modified src/auth.py"],
    "stderr_lines": [],
    "execution_metadata": {
      "model": "openrouter/gemini/gemini-3-flash-preview",
      "tokens_used": 2500,
      "duration_seconds": 145.5
    }
  },
  "job_history": [
    {
      "job_id": "JOB-abc123",
      "tool_name": "aider",
      "status": "done",
      "model": "openrouter/anthropic/claude-sonnet-4",
      "project_dir": "/home/user/projects/myapp",
      "prompt_excerpt": "Add user authentication...",
      "success": true,
      "exit_code": 0,
      "stdout_lines": ["Modified src/auth.py"],
      "stderr_lines": []
    },
    {
      "job_id": "JOB-def456",
      "tool_name": "human",
      "status": "done",
      "model": "",
      "prompt_excerpt": "Review authentication flow",
      "success": true
    }
  ],
  "comments": [...],
  "tags": ["backend", "security"],
  "files": ["src/auth.py", "tests/test_auth.py"],
  "estimated_hours": 4,
  "actual_hours": 3.5,
  "created_at": "2025-03-23T10:00:00Z",
  "updated_at": "2025-03-23T14:30:00Z",
  "completed_at": null
}
```

### Update Ticket

```
PUT /dashboard/tickets/{ticket_id}
```

Updates a ticket.

### Delete Ticket

```
DELETE /dashboard/tickets/{ticket_id}
```

Deletes a ticket.

### Deduplicate Tickets

Find and remove duplicate tickets. Duplicates are tickets with identical normalised (task, project_id, type).

```
POST /dashboard/tickets/dedup
```

**Request body:**
```json
{
  "dry_run": true
}
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `dry_run` | bool | `true` | If true, only report duplicates without removing them |

**Response:**
```json
{
  "duplicate_groups": 3,
  "total_duplicates": 78,
  "kept": ["TKT-0BA126", "TKT-25BA51", "TKT-C1871B"],
  "removed": ["TKT-780D93", "TKT-F46498", "..."],
  "dry_run": true
}
```

**CLI equivalent:** `proxym ticket dedup [--execute]`

### Add Comment

```
POST /dashboard/tickets/{ticket_id}/comments
```

Adds a comment to a ticket.

**Request Body:**
```json
{
  "author": "user@example.com",
  "content": "Started working on the JWT implementation"
}
```

### Assign Tool to Ticket

```
POST /dashboard/tickets/{ticket_id}/assign-tool
```

Assigns a tool to a ticket (without dispatching).

**Request Body:**
```json
{
  "tool": "aider",
  "agent_mode": "code",
  "model": "smart"
}
```

---

## Tool Instance Types

### Host Instance

Runs the tool binary directly on the host system.

```json
{
  "name": "host",
  "kind": "host",
  "command": ["aider"],
  "available": true,
  "description": "Run the aider CLI directly on the host."
}
```

### Docker Instance

Runs the tool as a Docker container or service.

```json
{
  "name": "docker",
  "kind": "docker",
  "service": "vscode",
  "profile": "vscode",
  "container_name": "proxym-vscode",
  "command": ["docker", "compose", "--profile", "vscode", "up", "-d", "vscode"],
  "available": true,
  "description": "VS Code Web running as the proxym Docker service."
}
```

### KVM Instance

Runs the tool inside a KVM/QEMU virtual machine.

```json
{
  "name": "kvm",
  "kind": "kvm",
  "vm_name": "dev-vm-01",
  "vm_host": "192.168.122.10",
  "vm_user": "developer",
  "vm_ssh_port": 22,
  "available": true,
  "description": "Development VM with full IDE stack",
  "notes": "VM managed by libvirt/KVM"
}
```

**Availability Check:**
- If `vm_host` and `vm_user` provided: checks via SSH (`ssh -o ConnectTimeout=2 user@host echo available`)
- If `vm_name` provided: checks via virsh (`virsh domstate vm_name`)

### VM Instance (Generic)

Generic VM instance reachable via SSH.

```json
{
  "name": "vm",
  "kind": "vm",
  "vm_host": "10.0.0.50",
  "vm_user": "ubuntu",
  "vm_ssh_port": 22,
  "available": true,
  "description": "Remote development VM"
}
```

---

## Executor Control

### Start Executor

```
POST /dashboard/tools/queue/start
```

Starts the background executor loop.

### Stop Executor

```
POST /dashboard/tools/queue/stop
```

Stops the background executor loop gracefully.

---

## Error Handling

All errors follow this format:

```json
{
  "detail": "Error description"
}
```

**HTTP Status Codes:**
- `200` - Success
- `400` - Bad request (invalid parameters)
- `404` - Resource not found
- `422` - Validation error (FastAPI/Pydantic)
- `500` - Internal server error

---

## Environment Variables

### Data Persistence

- `PROXYM_DATA_DIR` - Override the default SQLite storage path
  - Default: `~/.local/share/proxym/proxym.sqlite`
  - Docker: set to `/app/data` to persist to the `proxym-data` volume
  - All managers (tickets, accounts, projects, environments, users) share a single SQLite file via `SQLiteNamespaceStore`

### Tool Availability

- `PROXYM_TOOLS_AVAILABLE` - Force tools as available (comma-separated list or `*`)
  - Example: `PROXYM_TOOLS_AVAILABLE=aider,claude-code`
  - Useful when running inside container but dispatching to host binaries

### Tool Providers

Configure providers in `.env`:

```bash
OPENROUTER_API_KEY=sk-or-...
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
OLLAMA_HOST=http://localhost:11434
```

---

## WebSocket (Future)

Real-time job updates will be available via WebSocket at:

```
ws://localhost:4001/dashboard/ws
```

Events:
- `job.queued`
- `job.started`
- `job.completed`
- `job.failed`
- `job.cancelled`

---

## CLI Equivalents

| REST Endpoint | CLI Command |
|-------------|-------------|
| `GET /dashboard/tools/` | `proxym tools list` |
| `GET /dashboard/tools/healthcheck` | `proxym diagnose tools` |
| `POST /dashboard/tools/dispatch` | `proxym tools dispatch --ticket TKT-001 --tool aider` |
| `GET /dashboard/tools/queue` | `proxym tools queue` |
| `GET /dashboard/tickets` | `proxym ticket list` |
| `POST /dashboard/tickets` | `proxym ticket add "Task description"` |
| `GET /dashboard/tickets/{id}` | `proxym ticket show TKT-001` |

---

## Changelog

### 2025-07-18

- Added `PROXYM_DATA_DIR` environment variable for configurable SQLite persistence path
- All managers now persist to SQLite via `SQLiteNamespaceStore` — tickets, sprints, milestones, accounts, environments, projects, users
- Docker containers write to `/app/data/proxym.sqlite` via mounted volume
- LLM fallback execution: when tool binaries are unavailable, adapters delegate to OpenRouter (`openrouter/gemini/gemini-3-flash-preview`); execution metadata (model, provider, tokens, duration) stored in job results
- Tool instance support: host and docker-backed runtime instances with availability checks
- Instance-aware environment assignments (`instance_name` in `/dashboard/environments/assign`)

### 2025-03-23

- Added KVM/VM instance support for isolated project execution
- Added auto-fix endpoints (`/autofix`, `/autofix/bulk`)
- Added human tool for manual task assignment
- Added `job_history` to ticket details response
- Enhanced health check with `kvm_instance` and `vm_instance` flags
- Added execution metadata (model, tokens, duration) to job results
