Isolated no-docker recipe: uv venv for the backend, seeded scratch data dirs, built frontend via STATIC_DIR, Playwright from the page-scrape skill's node_modules. Records the networkidle/SSE gotcha. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57 lines
2.7 KiB
Markdown
57 lines
2.7 KiB
Markdown
---
|
||
name: verify
|
||
description: Run the ai-agent stack locally (isolated, no docker) and drive the built frontend with Playwright to verify a change end-to-end.
|
||
---
|
||
|
||
# Verifying ai-agent changes locally
|
||
|
||
Run the worktree's backend + built frontend fully isolated on a local port —
|
||
no docker rebuild, no touching the live container's data.
|
||
|
||
## Recipe
|
||
|
||
1. **Build the frontend**: `cd frontend && npm run build` (vite doesn't
|
||
typecheck; `npx tsc --noEmit` has pre-existing `@gabvdl/ui` type-drift
|
||
errors in files you didn't touch — ignore those).
|
||
2. **Backend venv** (host python has no fastapi; `python3 -m venv` lacks
|
||
ensurepip — use `uv`):
|
||
```bash
|
||
uv venv "$SCRATCH/venv"
|
||
uv pip install --python "$SCRATCH/venv/bin/python" -r backend/requirements.txt
|
||
```
|
||
3. **Seed isolated data**: copy a few real transcripts from the main
|
||
checkout's archive so the UI has real conversations:
|
||
```bash
|
||
mkdir -p "$SCRATCH"/data/transcripts/-home-gabrielvidal-homelab "$SCRATCH"/empty-transcripts
|
||
cd ~/homelab/services/ai-agent/data/transcripts/-home-gabrielvidal-homelab
|
||
ls -t *.jsonl | head -4 | xargs -I{} cp {} "$SCRATCH"/data/transcripts/-home-gabrielvidal-homelab/
|
||
echo '{}' > "$SCRATCH"/data/conversations-meta.json
|
||
```
|
||
4. **Run** (from `backend/`, port 8126; point TRANSCRIPTS_DIR at the empty
|
||
dir so it doesn't archive all of `~/.claude/projects`):
|
||
```bash
|
||
env WORKSPACE=<worktree-root> STATIC_DIR=<worktree>/services/ai-agent/frontend/dist \
|
||
DB_PATH=$SCRATCH/data/ai-agent.db TRANSCRIPTS_DIR=$SCRATCH/empty-transcripts \
|
||
PI_TRANSCRIPTS_DIR=$SCRATCH/empty-transcripts ARCHIVE_DIR=$SCRATCH/data/transcripts \
|
||
META_PATH=$SCRATCH/data/conversations-meta.json CRON_PATH=$SCRATCH/data/cron-jobs.json \
|
||
NOTIFY_PATH=$SCRATCH/data/notifications.json UI_STATE_PATH=$SCRATCH/data/ui-state.json \
|
||
UPLOADS_DIR=$SCRATCH/data/uploads SCREENSHOTS_DIR=$SCRATCH/data/screenshots \
|
||
ANTHROPIC_API_KEY= \
|
||
$SCRATCH/venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 8126
|
||
```
|
||
Health: `curl -s http://127.0.0.1:8126/api/health` → `{"ok":true}`.
|
||
5. **Drive with Playwright** from the page-scrape skill's install:
|
||
```js
|
||
import { chromium } from "/home/gabrielvidal/homelab/.claude/skills/page-scrape/node_modules/playwright/index.mjs";
|
||
```
|
||
Chromium browsers are already in `~/.cache/ms-playwright`.
|
||
|
||
## Gotchas
|
||
|
||
- `page.goto(..., {waitUntil: "networkidle"})` **never resolves** — the
|
||
`/api/events` SSE stream keeps the network busy. Use `"load"` + a short
|
||
`waitForTimeout`.
|
||
- Wire `page.on("console")` / `page.on("pageerror")` to catch runtime errors.
|
||
- At 1400×900 the left drawer (ConversationsPanel) is already visible; the
|
||
context menu opens with `card.click({button: "right"})`.
|