Files
sql-server-query-ai/README.md
T

102 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SQL Server qAI
Paste a SQL Server ShowPlan XML (or drop a `.sqlplan`), get a report with several ranked remediation options and
rewritten queries. Two models, one job: a **generative analyst model** proposes the options and writes the report, and
**Jev** (TypeSafe System One) scores every option and decides which one to run first. Jev never writes SQL; it returns
typed scores, a choice, and confidences. The report renders as OpenUI elements, not a markdown blob.
## Pipeline
1. `lib/digest.ts` parses the XML in code: top operators, missing indexes, warnings, waits, estimate-vs-actual row
errors, tables, statement text, subtree cost, parallelism. Raw XML never reaches a model.
2. The analyst model receives the digest JSON and proposes 2–4 genuinely different options (index, rewrite, statistics,
parallelism, schema), each with ordered action steps and an optional rewrite.
3. Jev answers four questions per option (`bottleneck_fit`, `semantic_safety`, `ease` `score`; `root_cause` `noul`) and
one cross-option call (`first_to_run` `choice`, `anything_worth_running` `noul`).
4. `lib/jev.ts` combines them with visible weights (0.40 / 0.30 / 0.15 / 0.15 — four numbers in that file, the only
tuning knob) and prints a verdict. Jev's pick leads only when its confidence clears 0.5; otherwise the report says
the order came from composite scoring.
5. The analyst streams the final report as OpenUI Lang; `<Renderer>` paints it as it arrives.
Getting the XML: SSMS → **Ctrl+M** (include actual execution plan) → run the query → right-click the Execution Plan tab
→ *Save As .sqlplan*. No SSMS: prefix the batch with `SET STATISTICS XML ON;` and copy the XML result cell.
## Run it
This repo runs as a plain Node process. Containerization is written (`Dockerfile`, Task 12 of the plan) but is not
required for local work — `npm run dev` is the normal path on a small machine.
```bash
npm install
cp .env.example .env.local # then fill in APP_SECRET and DATA_DIR
npm run dev # http://localhost:3000
```
`.env.local`:
| key | why |
| --- | --- |
| `APP_SECRET` | ≥16 chars. Encrypts API keys at rest (AES-256-GCM). Changing it makes stored keys unreadable. |
| `DATA_DIR` | where `qai.db` (SQLite, `node:sqlite`) lives. Default `./data`. Docker uses `/data`. |
Model keys are **not** config. Each user types them in the app (first-run guide or `/settings`), so a second user
brings their own endpoint and their own spend. Blank key field = keep the stored key.
- Analyst: any OpenAI-compatible base URL + key + model, plus optional extra JSON params.
A local endpoint such as `http://192.168.88.131:8888/v1` works; use key `EMPTY` when the server has no auth.
- Jev: a TypeSafe API key from `console.typesafe.ai/keys`, model usually `jev-latest`.
## Tests
```bash
npm test # node --test on tests/*.test.ts, no test framework installed
npm run build # production build + type check
npm run e2e # Playwright: signup, settings, real analyst + real Jev run, copy, print, history, 4 widths
```
The unit suites run offline: the analyst and Jev are exercised through injected `fetch`, so no key and no network.
`npm run e2e` is the opposite — it drives the real app against the real models, and reads `JEV_API_KEY` from
`.env.local`. Expect it to be slow; that is the models, not the harness.
`tests/digest.test.ts` skips unless a genuine plan exists at `fixtures/real.sqlplan`. Drop one there from SSMS and the
skip becomes the real check on ShowPlan attribute spellings.
## Git remote (Gitea)
Origin points at the self-hosted Gitea:
```bash
git remote -v # http://192.168.88.39:3000/ahmed/sql-server-query-ai.git
git push origin feat/sql-server-qai
```
The remote URL deliberately contains **no password**. Git prompts for the username (`ahmed`) and password the first
time, or you can keep them out of prompts:
```bash
git config credential.helper osxkeychain # remember them locally
git push origin feat/sql-server-qai
```
Never commit the password into `.git/config`, a remote URL, or this README — a stored credential in the repo is
readable by whoever you hand the repo to. If you want it non-interactive in CI, create a Gitea token
(Settings → Applications) and use `http://192.168.88.39:3000/ahmed/sql-server-query-ai.git` with the token as password.
## Layout
```
lib/digest.ts XML → bounded digest (the only shape models see)
lib/analyst.ts propose 2–4 options; stream the final OpenUI report
lib/jev.ts questions, weights, ranking, verdict, fallback
lib/report-ui.tsx OpenUI component library — the same module builds the prompt and renders the answer
lib/db.ts node:sqlite: users, sessions, settings, analyses
lib/vault.ts AES-256-GCM seal/open/mask for credentials
lib/auth.ts scrypt passwords, hashed session tokens (DB stores the SHA-256, never the token)
app/api/analyze SSE pipeline: digesting → proposing → judging → writing
tests/ offline unit suites tests-e2e/ Playwright
docs/superpowers/ spec + the 13-task implementation plan this was built from
```
Design: dark terminal console, JetBrains Mono for data, IBM Plex Sans for prose, one phosphor accent.
Print stylesheet flips to paper white and drops the rail, buttons and chrome — that is the Export to PDF path.