Metadata-Version: 2.4
Name: getbased-dashboard
Version: 0.6.8
Summary: Web dashboard for getbased-agents — manage knowledge libraries, generate MCP client configs, inspect agent activity
License-Expression: AGPL-3.0-or-later
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.29
Requires-Dist: httpx>=0.27
Requires-Dist: typer>=0.12
Requires-Dist: python-multipart>=0.0.31
Requires-Dist: getbased-mcp>=0.2.9
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
Requires-Dist: respx>=0.21; extra == "test"
Requires-Dist: httpx>=0.27; extra == "test"
Dynamic: license-file

# getbased-dashboard

Web dashboard for [getbased-agents](https://github.com/elkimek/getbased-agents). It lets you manage knowledge libraries, generate MCP client config, test the MCP adapter, and inspect recent agent activity.

---

## What it looks like

Three tabs, one auth gate, and a bottom-right ingest progress pill that survives tab changes.

### Knowledge tab
- Engine badge strip at the top: `ONNX · CPU · MiniLM-L6-v2 · 384d · floor 0.55 · ready`
- Library list with per-row model chip, live chunk count (`12,758 chunks`), relative last-ingested (`indexed 2h ago`), activate/rename/delete
- Create-library form with a model dropdown (MiniLM-L6-v2 · BGE-small/base/large-en · BGE-M3) — dimension + download size shown per option
- Drag-drop ingest with a bottom-right pill: HTML5 `<progress>`, `12,500 / 16,000 · 3.2/s` chunks/sec rate, Cancel (partial commit) + Dismiss (×). 3s auto-dismiss on completion.
- Search preview with score per result
- Sources panel sorted by chunk count desc, Delete-all + per-source delete

- MCP tab
- Env viewer showing what a spawned MCP would see (`LENS_URL`, `LENS_API_KEY_FILE` + present/missing, `GETBASED_TOKEN` and `GETBASED_AGENT_CONTEXT_KEY` set/not set, module path). Tooltips explain the difference between the dashboard environment and the environment an MCP client will pass to the server.
- Config generator — emits paste-ready blocks for **Claude Desktop**, **Claude Code**, **Cursor**, **Cline**, **Codex CLI**, **Hermes**, and **OpenClaw**. Generated config uses `GETBASED_STACK_MANAGED=1` so secrets stay in the shared getbased env file, not in the client config.
- "Test MCP" — spawns the real `getbased-mcp` binary via stdio, runs `initialize` + `tools/list`, returns elapsed ms + tool names

### Activity tab
- Top-line stat cards (total calls, errors, error rate, tools in use)
- Per-tool table with P50/P95 latency
- Newest-first feed of recent calls, polls every 10s
- Clear log button

---

## Install and run

```bash
pipx install getbased-dashboard
getbased-dashboard serve          # http://127.0.0.1:8323
```

The dashboard expects a [getbased-rag](https://github.com/elkimek/getbased-agents/tree/main/packages/rag) server at `http://127.0.0.1:8322` and reuses rag's API key. On first visit the UI prompts for the bearer key; it's stored in `localStorage` on your machine.

Or as part of the full stack:

```bash
pipx install "getbased-agent-stack[full]"
lens serve                       # in one terminal — the local knowledge server
getbased-dashboard serve         # in another — the UI
```

---

## Architecture

```
  Browser                 Dashboard               Rag server            MCP subprocess
  localhost        ↔      localhost         ↔     localhost             on-demand stdio
                          /api/* proxy            /query, /ingest,      tools/list
                          + MCP test spawn        /libraries, /info,    (for Test button)
                          + activity tail         /models, /stats
```

The dashboard holds no data. Delete it and your knowledge base is untouched.

- All `/api/*` routes bearer-auth'd with the same key rag + MCP use (`secrets.compare_digest`, constant-time)
- Error envelope normalised to `{"error": "<string>"}` for both HTTPException and Pydantic validation errors — frontend has one shape to parse
- Upload path streams chunk-by-chunk to a temp file with a byte cap enforced before buffering (no OOM-via-multi-GB-upload)
- Client disconnect propagates: browser aborts fetch → dashboard drops upstream → rag sees disconnect → ingest stops at next batch boundary

---

## Config

| Variable | Default | Description |
|---|---|---|
| `DASHBOARD_HOST` | `127.0.0.1` | Bind host. Loopback-only by default — expose to LAN at your own risk |
| `DASHBOARD_PORT` | `8323` | Bind port |
| `LENS_URL` | `http://127.0.0.1:8322` | Where the rag server lives |
| `LENS_API_KEY_FILE` | `$XDG_DATA_HOME/getbased/lens/api_key` (with legacy fallback to `~/.hermes/rag/lens_api_key`) | Shared bearer token — same one MCP reads |
| `DASHBOARD_ACTIVITY_LOG` | `$XDG_STATE_HOME/getbased/mcp/activity.jsonl` | JSONL path the MCP writes to; dashboard tails it |
| `DASHBOARD_MAX_INGEST_BYTES` | `268435456` (256 MB) | Cap on a single upload's total size |
| `GETBASED_TOKEN` / `GETBASED_AGENT_CONTEXT_KEY` | (from env) | Optional. When set, the MCP tab's env viewer reads "set". Stack-managed client configs normally avoid embedding these secrets and read them from the shared getbased env file instead. |

---

## CLI

```
getbased-dashboard serve       Start the web server. Prints a one-click
                               `?key=…` login URL tagged [LOGIN-URL] so
                               users don't need to copy-paste the bearer
                               out of the terminal.

getbased-dashboard login-url   Re-print the magic login URL on demand.
                               Use this after closing the original
                               `serve` terminal or when running as a
                               systemd / launchd service. Exits non-zero
                               if no key is on disk.

getbased-dashboard info        Show resolved config + whether the rag
                               key is on disk. Never echoes the key
                               itself — safe to paste into a bug report.
```

When running under systemd, the login URL is also grep-able in the
service logs:

```
journalctl --user -u getbased-dashboard | grep LOGIN-URL
```

---

## Security notes

- Dashboard binds loopback by default. Exposing via `DASHBOARD_HOST=0.0.0.0` means anyone on the LAN can drive your rag with the bearer key
- The bearer key is read fresh from disk on every authed request — rotating the key (rewrite the file) takes effect without a dashboard restart
- Multipart upload filenames are basename-sanitised before forwarding to rag (defence in depth; rag also sanitises)
- Subprocess spawn for the MCP test button reaps the child on timeout, exception, or cancellation — no orphaned processes

---

## License

AGPL-3.0-or-later, matching the rest of the monorepo.
