{"id":50472444,"url":"https://github.com/semcod/wupbro","last_synced_at":"2026-06-01T11:03:35.657Z","repository":{"id":354732029,"uuid":"1224927895","full_name":"semcod/wupbro","owner":"semcod","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-29T19:22:06.000Z","size":177,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T21:26:38.109Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/semcod.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T19:17:00.000Z","updated_at":"2026-04-29T19:22:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/semcod/wupbro","commit_stats":null,"previous_names":["semcod/wupbro"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/semcod/wupbro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fwupbro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fwupbro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fwupbro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fwupbro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/semcod","download_url":"https://codeload.github.com/semcod/wupbro/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fwupbro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33771630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-01T11:03:35.591Z","updated_at":"2026-06-01T11:03:35.642Z","avatar_url":"https://github.com/semcod.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wupbro\n\n\n## AI Cost Tracking\n\n![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.11-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)\n![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.15-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-2.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)\n\n- 🤖 **LLM usage:** $0.1500 (1 commits)\n- 👤 **Human dev:** ~$200 (2.0h @ $100/h, 30min dedup)\n\nGenerated on 2026-04-29 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)\n\n---\n\nFastAPI backend + minimal HTML dashboard for the WUP regression watcher.\n\n## Architecture\n\n```\n┌──────────────────────┐   POST /events    ┌──────────────────────┐\n│  WUP agent (shell)   │ ───────────────▶  │  wupbro (FastAPI)    │\n│  - file watcher      │                   │  - /events (sink)    │\n│  - testql runner     │                   │  - /drivers/*        │\n│  - visual diff       │                   │  - /dashboard (UI)   │\n└──────────────────────┘                   └──────────────────────┘\n                                                      │\n                                                      ▼\n                                            ┌─────────────────┐\n                                            │ Browser UI      │\n                                            │ (auto-refresh)  │\n                                            └─────────────────┘\n```\n\n## Endpoints\n\n| Path                              | Method | Purpose                                     |\n|-----------------------------------|--------|---------------------------------------------|\n| `/events`                         | POST   | Receive event from a WUP agent              |\n| `/events`                         | GET    | List recent events (filter by type/service) |\n| `/events/stats`                   | GET    | Aggregate counts by type                    |\n| `/events`                         | DELETE | Clear store (admin/debug)                   |\n| `/drivers/dom-diff/capture`       | POST   | One-shot Playwright DOM snapshot + diff     |\n| `/drivers/browserless/screenshot` | POST   | Proxy to a `browserless/chrome` container   |\n| `/drivers/anomaly/report`         | POST   | Record numeric anomaly as ANOMALY event     |\n| `/drivers/health`                 | GET    | Driver capability discovery                 |\n| `/`, `/dashboard`                 | GET    | HTML dashboard                              |\n| `/healthz`                        | GET    | Liveness probe                              |\n| `/openapi.json`, `/docs`          | GET    | OpenAPI spec + Swagger UI                   |\n\n## Event types\n\n`REGRESSION`, `PASS`, `ANOMALY`, `VISUAL_DIFF`, `HEALTH_TRANSITION`.\n\nSchema (Pydantic):\n\n```json\n{\n  \"type\": \"REGRESSION\",\n  \"service\": \"users-web\",\n  \"file\": \"app/users/routes.py\",\n  \"endpoint\": \"/api/users\",\n  \"status\": \"fail\",\n  \"stage\": \"quick\",\n  \"reason\": \"TestQL exit code 1\",\n  \"timestamp\": 1730000000\n}\n```\n\nExtra fields are preserved via `model_config = {\"extra\": \"allow\"}`.\n\n## Run\n\n```bash\n# Install\npip install -e wupbro/\n\n# Dev server (auto-reload)\nwupbro --reload --port 8000\n\n# Or directly\nuvicorn wupbro.main:app --host 0.0.0.0 --port 8000 --reload\n```\n\nDashboard: \u003chttp://localhost:8000/\u003e\n\nOpenAPI docs: \u003chttp://localhost:8000/docs\u003e\n\n## Configure WUP agent to send events\n\nIn your `wup.yaml`:\n\n```yaml\nweb:\n  enabled: true\n  endpoint: \"http://localhost:8000\"\n  endpoint_env: \"WUPBRO_ENDPOINT\"   # fallback if endpoint is empty\n  timeout_s: 2.0                     # short — must not block watcher\n  api_key: \"\"                        # optional bearer token\n```\n\nOr via environment variable:\n\n```bash\nexport WUPBRO_ENDPOINT=http://localhost:8000\nwup watch . --mode testql\n```\n\nThe agent will POST events fire-and-forget on:\n\n- service health transitions (up ↔ down)\n- regressions (when TestQL fails)\n- visual DOM diffs (when significant changes detected)\n\n## Browserless integration\n\n```bash\ndocker run -d --name browserless -p 3000:3000 browserless/chrome\nexport BROWSERLESS_URL=http://localhost:3000\nwupbro\n```\n\nThen:\n\n```bash\ncurl -X POST http://localhost:8000/drivers/browserless/screenshot \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://example.com\", \"full_page\": true}'\n```\n\n## Storage\n\nEvents are kept in an in-memory ring buffer (capacity 1000) and persisted to `.wupbro/events.jsonl` for restart durability.\n\n## Tests\n\n```bash\nPYTHONPATH=wupbro python3 -m pytest wupbro/tests/ -v\n```\n\n17 tests covering events router, drivers (anomaly, browserless, dom-diff, health), dashboard HTML, OpenAPI schema.\n\n## License\n\nLicensed under Apache-2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemcod%2Fwupbro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsemcod%2Fwupbro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemcod%2Fwupbro/lists"}