191 lines
12 KiB
Markdown
191 lines
12 KiB
Markdown
---
|
|
name: rpa-dashboard-ai
|
|
description: Builds a working dashboard for an RPA bot or service that uses AI (an LLM or OCR extraction call). It has everything from rpa-dashboard-no-ai plus confidence bands, a review split pane (source document beside the extracted fields, band filters, drafts, Verify), an approve gate the backend enforces, and a cost/ROI page (tokens and cost per run, monthly spend, an against-doing-it-by-hand panel). Web: React + Vite + Tailwind with a sample-data server stub; desktop (PyQt): plain-HTML AI sections over the Qt bridge. Use when the user asks for an "AI RPA dashboard", an "extraction dashboard", an "LLM/OCR review dashboard", or any RPA/bot dashboard in a project that calls an LLM or OCR to extract fields. Needs rpa-dashboard-no-ai installed next to it.
|
|
---
|
|
|
|
# RPA dashboard (AI)
|
|
|
|
Everything this skill needs is bundled. Never read the original source projects.
|
|
Shared files live in the no-AI skill, installed next to this one: `<no-ai>` below
|
|
means `../rpa-dashboard-no-ai/templates/`.
|
|
|
|
**Paths:** both skills must be installed side by side (same parent folder). Resolve
|
|
`templates/...` against this skill's own folder (the one holding this SKILL.md), and
|
|
`<no-ai>` against it too (`<this skill>/../rpa-dashboard-no-ai/templates/`), never against
|
|
the user's project. Run the scripts with those absolute paths, from the user's project, for
|
|
example `python <this skill>/../rpa-dashboard-no-ai/templates/detect_frontend.py <project root>`.
|
|
|
|
| File | What it is |
|
|
|---|---|
|
|
| `templates/web/` | The React + Vite + Tailwind starter: shell, KPI, donut, run panel, report, **band legend, review split pane, approve gate, cost page**, sample data. |
|
|
| `templates/web/pricing.py` | The pricing table (with its source and as-of date) and `cost_for_call`. The backend imports it. |
|
|
| `templates/web/server_stub.py` | Sample-data backend for runs, review rows and the approve gate. Standard library only. |
|
|
| `templates/web/bands.py` | The band cut points and rules. The one source of truth: the backend imports it. |
|
|
| `templates/desktop/ai_sections.html` | Desktop, and web projects with a non-React frontend: the Review tab (band legend, review split pane, drafts, Verify, approve gate) and the Cost tab in plain HTML, pasted into `<no-ai>dashboard.html`. Talks over the Qt bridge, or with no Qt, fetches the `templates/contract.md` endpoints. |
|
|
| `templates/desktop/ai_bridge.py` | Desktop: the no-AI `Bridge` plus the `ai_request` slot that hands every AI request to the Python review backend. |
|
|
| `templates/contract.md` | The AI contract: runs, review rows, endpoints and the gate, over HTTP or the Qt bridge. Extends `<no-ai>contract.md`. |
|
|
| `templates/reference/` | Superbill Review extracts, marked EXAMPLE ONLY. Use them to port extra polish, never copy their project names. |
|
|
| `<no-ai>frontend.md`, `<no-ai>detect_frontend.py` | Existing frontend: detect, report, keep or restyle. |
|
|
| `<no-ai>themes.md`, `<no-ai>palette.py` | Theme presets and the custom-colour steps. |
|
|
| `<no-ai>contract.md` | The no-AI contract the AI one extends. |
|
|
|
|
The questions are the same as the no-AI skill's, in the same order. Ask one at a
|
|
time and wait for the answer. If the user's request already answers a question,
|
|
don't ask it again.
|
|
|
|
## 1. Scan the project
|
|
|
|
Before asking anything:
|
|
- **Frontend:** run `python <no-ai>detect_frontend.py <project root>` and read
|
|
`<no-ai>frontend.md` section 1.
|
|
- **AI call:** find the LLM or OCR extraction (for example `genai`, `openai`,
|
|
`anthropic`, Textract or Tesseract calls): which fields it returns, which are
|
|
mandatory, and whether it returns per-word scores. Note the provider, the model
|
|
names, and whether the response's token usage (input, output, thinking) is kept.
|
|
- **Bot or backend:** the entry point, what it prints, and any web framework
|
|
(FastAPI, Flask, Django).
|
|
|
|
If the project has no AI call at all, say so and suggest `rpa-dashboard-no-ai`.
|
|
|
|
## 2. Report the frontend, then ask keep or restyle
|
|
|
|
Follow `<no-ai>frontend.md` sections 2 to 5.
|
|
- **No frontend:** say "No existing frontend found." and go to step 3.
|
|
- **Frontend found:** say "Frontend found at `<path>`, stack `<stack>`, colours
|
|
`<main tokens>`." Then ask: **keep its look**, or **restyle** it?
|
|
|
|
## 3. Ask for colours
|
|
|
|
Skip this if the user chose keep. Offer:
|
|
1. **Tebra Sky**: blue glass cards on a sky gradient.
|
|
2. **Superbill Ember**: flat surfaces with a red-orange brand gradient.
|
|
3. **Custom**: the user gives one brand hex colour.
|
|
|
|
## 4. Ask desktop or web
|
|
|
|
Ask only if there is no frontend. If there is one, use its stack. If the project
|
|
uses PyQt, choose desktop and say so.
|
|
- **Web:** the React starter in `templates/web/`, served by the backend. An existing
|
|
non-React frontend gets the plain-HTML page instead (step 6, web).
|
|
- **Desktop:** the no-AI PyQt page with `templates/desktop/ai_sections.html` pasted
|
|
in, hosted by `templates/desktop/ai_bridge.py`. No web server, no npm.
|
|
|
|
## 5. Ask which optional sections to build
|
|
|
|
Always built: the no-AI shell and sections, plus the band legend, the review split
|
|
pane, the approve gate and the cost page. Ask which extras to add (choose any, or none):
|
|
**checkpoint tracker**, **admin/roles screen**, **login page**, **model picker** (choose
|
|
the model per batch), **retry on another model** (for failed runs). Build only the
|
|
chosen ones at their `OPTIONAL:` markers, and delete the markers.
|
|
- **Checkpoint tracker, admin/roles, login:** web: port them from `<no-ai>dashboard.html`'s
|
|
`OPTIONAL:` blocks to the markers in `RunPanel.tsx` (checkpoints) and `App.tsx` (admin tab
|
|
and screen, login). Desktop: they're already in the no-AI page; `<no-ai>sections.py` keeps
|
|
the chosen ones (no-AI step 6), and `<no-ai>sections.md` says what each needs from the host.
|
|
- **Model picker:** a `<select>` filled from `GET /models` (the pricing table's keys), at
|
|
the marker in `Cost.tsx` (desktop: `ai_sections.html`) or next to the Run button; the chosen model goes with the
|
|
batch's start action.
|
|
- **Retry on another model:** on a `failed` run, at the marker in `Review.tsx` (desktop: `ai_sections.html`): a model
|
|
`<select>` (from `GET /models`, defaulting to the run's own model) and a Retry button
|
|
that sends `POST /runs/{job_id}/retry {model}`, then polls the run as usual.
|
|
Both need the endpoints in `templates/contract.md`; add them to the backend (and the stub).
|
|
|
|
## 6. Build (web)
|
|
|
|
**Existing plain-HTML, Vue, Angular or Svelte frontend:** don't use the React starter.
|
|
Build the no-AI page as `../rpa-dashboard-no-ai/SKILL.md` step 6 says (web, with
|
|
`API_BASE` filled, for example `/api`), paste the whole of `templates/desktop/ai_sections.html`
|
|
into it just before `</body>`, and put it where `<no-ai>frontend.md` section 3 says. With no
|
|
Qt bridge, its AI sections fetch `{API_BASE}` + the paths in `templates/contract.md`, so
|
|
the backend serves those (step 7). Port it into the app's components only if the user asks,
|
|
with `ai_sections.html` as the reference. Then skip to step 7.
|
|
|
|
1. Copy `templates/web/` into the project as `dashboard/` (an existing React app:
|
|
port the `src/` components into it, see `<no-ai>frontend.md` section 3).
|
|
Don't copy `node_modules/` or `dist/`.
|
|
2. Fill every `{{...}}` in `dashboard/index.html`'s CONFIG block:
|
|
|
|
| Placeholder | Value |
|
|
|---|---|
|
|
| `APP_NAME`, `APP_SUBTITLE` | The project's name and a short tagline. |
|
|
| `LOGO_SRC` | The logo's path, or empty. |
|
|
| `STEPS_JSON` | The run steps as a JSON list, for example `["Initializing","Extract","Review","Completed"]`. |
|
|
| `REPORT_COLUMNS_JSON` | `[{"key":..., "label":...}]`, with a `status` column. |
|
|
| `API_BASE` | `/api` unless the backend mounts the dashboard API elsewhere. Keep it equal to `API` in `server_stub.py`. |
|
|
|
|
3. Apply the theme in `dashboard/src/index.css` only: replace the `body{...}` and
|
|
`body.dark{...}` token blocks with the preset from `<no-ai>themes.md` (for Ember,
|
|
add its font `<link>` to `index.html`'s `<head>`), or with
|
|
`python <no-ai>palette.py "<hex>"` tokens for a custom colour, showing the user
|
|
its contrast table. For keep, fill them from the project's tokens
|
|
(`<no-ai>frontend.md` section 4). Never change the band colour block.
|
|
4. Search the output for `{{`. None may be left.
|
|
|
|
## 6. Build (desktop)
|
|
|
|
1. Build the no-AI desktop page and host first, exactly as steps 6 and 7 of
|
|
`../rpa-dashboard-no-ai/SKILL.md` say: `dashboard/dashboard.html` (theme, placeholders,
|
|
`SAMPLE_DATA = false` once the bot is wired), `bridge.py` and `bot_runner.py`.
|
|
2. Paste the whole of `templates/desktop/ai_sections.html` (Review and Cost tabs) into `dashboard/dashboard.html`,
|
|
just before `</body>`. Change nothing in it: it uses the page's theme tokens, and its
|
|
band colours are fixed.
|
|
3. Copy `templates/desktop/ai_bridge.py`, `templates/web/server_stub.py`,
|
|
`templates/web/bands.py` and `templates/web/pricing.py` into `dashboard/`. Fill `{{APP_NAME}}` in `ai_bridge.py`.
|
|
4. The app now starts with `python dashboard/ai_bridge.py` (not `bridge.py`).
|
|
5. Search the output for `{{`. None may be left.
|
|
|
|
## 7. Wire the data
|
|
|
|
The contracts: `<no-ai>contract.md` for the shell, `templates/contract.md` for runs,
|
|
review rows and the gate.
|
|
- **Sample data (no backend for these endpoints yet):** keep `SAMPLE_DATA = true` in
|
|
`src/store.ts` (a plain-HTML page: in `dashboard.html`) and use `server_stub.py`. Replace its `SAMPLE_FIELDS` with the
|
|
fields the project's extraction really returns (name, a sample value, word scores,
|
|
mandatory). Tell the user which endpoints their backend must serve later.
|
|
- **Backend exists:** add the endpoints from `templates/contract.md` to it. Copy
|
|
`bands.py` next to it and band every field with `field_band(word_scores, value,
|
|
mandatory)`. The approve endpoint must refuse (409 with `detail`) while any flagged
|
|
field is unverified: the page never decides that. For the shell, set
|
|
`SAMPLE_DATA = false` and serve the no-AI endpoints too.
|
|
- **Cost page:** copy `pricing.py` next to the backend. Fill `PRICING` with the rates of
|
|
the models the project really calls, from the provider's pricing page, and set
|
|
`PRICING_SOURCE` and `PRICING_AS_OF`. If you can't read the rates, ask the user for
|
|
them. The backend stores each run's token usage and serves `GET /roi`, pricing each run
|
|
with `cost_for_call`. A run with no recorded usage gets `null`, never 0. If the
|
|
extraction doesn't keep token usage yet, wire it to (for example Gemini's
|
|
`usage_metadata`, OpenAI's and Anthropic's `usage`). In sample mode, replace the stub's
|
|
`ROI_RUNS` models with the project's models.
|
|
- **Desktop:** the same rules, over the bridge (`templates/contract.md`, "Desktop").
|
|
The shell is wired in `bot_runner.py` as the no-AI skill says. For review data, keep
|
|
`server_stub.py` (replace its `SAMPLE_FIELDS` with the real fields, as above) until
|
|
the project stores its extraction results. Then write a module with the same
|
|
`dispatch(method, path, body)` over the project's store (same routes, bands from
|
|
`bands.py`, approve refused while flagged fields are unverified) and import it in
|
|
`ai_bridge.py` instead of `server_stub`. The page never decides approval.
|
|
- Never invent fields, model names or prices the project doesn't have.
|
|
|
|
## 8. Verify
|
|
|
|
```
|
|
cd dashboard
|
|
npm install
|
|
npm run build
|
|
python server_stub.py # page + sample API on http://127.0.0.1:8000
|
|
```
|
|
|
|
Open the page and check, in light, dark (the toggle) and a window 820px wide or less:
|
|
- the dashboard, the run panel and the Report tab show sample data;
|
|
- on Review: the band legend counts and the caveat, band filters, a typed edit marked
|
|
unsaved until Save, a refused Approve while flagged fields are unverified, and
|
|
"page X of Y" on a running document;
|
|
- on Cost: the coverage pill, total and this month's spend, the month table, a run
|
|
marked "not priced", the pricing source and as-of date, and the by-hand figure
|
|
changing when an assumption is edited;
|
|
- no `{{` is left and the console shows no script errors.
|
|
|
|
Desktop: `python dashboard/bot_runner.py` (dry run: real steps, ending at 100), then
|
|
`python dashboard/ai_bridge.py`, and check the same list in the window.
|
|
|
|
If you can't run npm (or open a window) here, say so and give the user these commands. Finish by
|
|
telling the user where the files are, which theme and sections were built, and
|
|
whether the review data is sample data or the backend's.
|