6.4 KiB
6.4 KiB
Repository Guidelines (Agent-Facing)
What This Project Is
- Guided demo platform built on FastAPI + Playwright to showcase browser automations and GraphQL-backed data flows.
- Entry point:
src/guide/app/main.py; CLI runner:python -m guide(respectsHOST/PORT). - Personas and host targets are data-driven via YAML, not hardcoded.
- App state wiring happens in
create_app(): loads settings, buildsPersonaStore,ActionRegistry, andBrowserClient, then stashes them onapp.statefor dependency injection.
Code & Module Layout
- Source root:
src/guide/app/actions/— FastAPI-triggered demo actions; keep them thin, declarative, and side-effect scoped.auth/— pluggable MFA/auth helpers; avoid coupling to specific IdPs.browser/—BrowserClientand Playwright wrappers; centralize navigation, timeouts, and tracing.core/— settings, logging, dependency wiring;AppSettingsdrives runtime config and reads YAML/env merges.errors/—GuideErrorhierarchy; routes standardize error responses.raindrop/— GraphQL client + operations; isolate schemas/operations from business logic.strings/— selectors, labels, copy, GraphQL strings; no inline literals in actions.models/— domain/persona models; prefer pydantic v2 models with explicit types.utils/— shared helpers; keep <300 LoC and avoid circular deps.
- Config files:
config/hosts.yaml,config/personas.yamldescribe targets/personas; never embed secrets. ENV overrides:RAINDROP_DEMO_BROWSER_HOSTS_JSONandRAINDROP_DEMO_PERSONAS_JSONaccept JSON arrays of objects matching the YAML shape.
Development Workflow
- Install deps:
pip install -e . - Type check:
basedpyright src - Sanity compile:
python -m compileall src/guide - Run API (dev):
python -m guide - Preferred loop: edit →
basedpyright→compileall→ manual smoke via CLI or hitting local/docs. - API surface (2025-11-22):
GET /healthz– liveness.GET /actions– list action metadata.POST /actions/{id}/execute– run an action; yieldsActionEnvelopewith correlation_id.GET /config/browser-hosts– current default + host map.
Coding Conventions
- Python 3.12+, Pydantic v2, pydantic-settings.
- Use PEP 604 unions (
str | None), built-in generics (list[str],dict[str, JSONValue]). - Ban
Anyand# type: ignore; add type guards instead. - Actions/constants: use
ClassVar[str]for IDs/descriptions. - Keep modules small (<300 LoC); split by domain (e.g.,
actions/intake/basic.py). - Strings/queries belong in
strings/; selectors should be reusable and labeled. strings.serviceenforces domain names; missing keys raise immediately, so keep selectors/texts in sync with UI.
Error Handling & Logging
- Raise
GuideErrorsubclasses; let routers translate to consistent HTTP responses. - Log via
core/logging(structured, levelled). Include persona/action ids and host targets in logs for traceability. - For browser flows, prefer Playwright traces over ad-hoc prints; disable tracing only intentionally.
BrowserClient.open_pageresolves host by ID → CDP attach (reuses existing Raindrop page) or launches headless chromium/firefox/webkit; always close context/browser on exit.- CDP mode requires
host+portinhosts.yaml; errors surface asBrowserConnectionErrorwith host_id detail.
Browser Automation Notes
- Route all CDP calls through
BrowserClient; configure timeouts/retries there, not per action. - Keep selectors in
strings/; avoid brittle text selectors—prefer data-testid / aria labels when available. - When mocking Playwright in tests, isolate side effects and avoid real network/CDP hits.
- Current MFA flow uses
DummyMfaCodeProviderwhich raisesNotImplementedError; real runs need a provider implementation or override before executing login/ensure_persona.
GraphQL & Data Layer
raindrop/graphql.pyhouses the client; operations live inraindrop/operations. Keep queries/mutations versioned and colocated with types instrings/.- Validate responses with pydantic models; surface schema mismatches as
GuideError. - Never bake URLs/tokens—pull from
AppSettingsand YAML/env overrides. - HTTP transport via
httpx.AsyncClient(10s timeout); GraphQL errors bubble asGraphQLTransportErrororGraphQLOperationErrorwith returnederrorspayload indetails.
Configuration & Secrets
- Runtime configuration flows: env vars →
config/*.yaml→AppSettingsdefaults. - Do not commit credentials; use env overrides for tokens/hosts.
- MFA providers are pluggable; keep provider-specific wiring behind interfaces.
- Default env prefix:
RAINDROP_DEMO_(seeAppSettings.model_config).
Testing Expectations
- Minimum:
basedpyright srcandpython -m compileall src/guidebefore publishing. - Add unit tests under
tests/alongside code; mock Playwright/GraphQL; avoid real external calls. - Prefer deterministic fixtures; document any required env vars in test module docstrings.
- Action pipeline happy-path: request → resolve persona + browser host →
BrowserClient.open_page→ optionalensure_persona→ action.run →ActionEnvelopewith correlation_id fromActionContext.
Git & PR Hygiene
- Commits: scoped and descriptive (e.g.,
feat: add auth login action,chore: tighten typing). - PRs should state changes, commands run, and any config additions (
hosts.yaml,personas.yaml). - Link related issues; include screenshots/log snippets when UI or API behavior changes.
Performance & Footprint
- Keep browser sessions short-lived; close contexts to avoid leaking handles.
- Cache expensive GraphQL lookups when safe; prefer per-request timeouts over global sleeps.
- Avoid widening dependencies; stick to project pins unless justified.
- Close Playwright contexts/browser handles promptly (client already wraps in contextmanager; keep action code lean to avoid dangling pages).
Quick Start Checklist (new agents)
- Create/verify
config/hosts.yamlandconfig/personas.yamlmatch your target env. - Run
pip install -e . - Run
basedpyright srcandpython -m compileall src/guide. - Start API:
python -m guideand open/docsto smoke basic actions. - Review
strings/for selectors relevant to your feature before writing new actions. - If executing auth flows, supply a working
MfaCodeProvider(current dummy raises) or stub the login call in demos/tests.