- ChatPanel: add 'chat-message ${role}' CSS classes to message wrappers
so .chat-message.user and .chat-message.assistant rules apply correctly
- LoginPage: rename className 'login-error' -> 'error' to match the
.login-card .error selector in globals.css
- MCPAppRenderer: verify event.source matches iframe contentWindow before
processing postMessage to close cross-window injection vector
- App: remove redundant await refresh() after createNew() since
createNew() already calls refresh() internally
- useArtifacts: wrap listArtifacts call in try/catch with console.error,
matching the error-handling pattern already used in useSessions
- backend/app.py: add Depends(_require_auth) to /api/copilotkit endpoint (critical
security fix — endpoint was fully unprotected; now requires valid session cookie)
- backend/app.py: move 'from ag_ui.core import RunStartedEvent' from inline function
body to top-level imports (style consistency)
- backend/auth.py: remove dead AUTH_PASS_HASH module-level constant (verify_password
already reads from os.environ at call time; the cached binding was unused dead code)
- backend/artifacts.py: add path traversal guards to list_artifacts, get_artifact,
and save_artifact — resolve paths and verify they stay within ARTIFACTS_DIR
- entrypoint.sh: health-check loop now sets READY flag and exits 1 if amplifierd
fails to start within 30s (previously fell through silently, causing 502s)
- tests/test_app.py: add TestCopilotKitAuth — verifies unauthenticated requests to
/api/copilotkit return 401; includes note explaining why streaming is not tested here
- tests/test_structure.sh: update to reflect that Dockerfile and entrypoint.sh now
exist (created in Tasks 7+8); convert absent-checks to presence-checks
Co-authored-by: Amplifier <amplifier@anthropic.com>
- Renamed repo from car-help to research-workbench
- Remote now points to git.ampbox.io/ken/research-workbench
- cloudflared: research.ampbox.io (app) + vnc.ampbox.io (browser)
- Updated all references from browser.ampbox.io to research.ampbox.io
- Search box: type anything, toggle filter pills (hybrid, price range, distance, etc.)
- Backend calls Anthropic to parse query into search params
- Playwright crawls Craigslist, CarGurus, AutoTempest with dynamic URLs
- Results scored/ranked with car-specific scoring engine
- Second Anthropic call generates a custom buying guide from actual results
- Guide sections: top picks, checklist, mechanics, negotiation, budget
- All visible live in the browser panel via noVNC
- FastAPI httpx proxy can't handle WebSocket upgrades (status 101)
- noVNC iframe now points to vnc.ampbox.io (port 6080 via cloudflared)
- App UI stays at browser.ampbox.io (port 8080 via cloudflared)
- Auto-detects local vs ampbox.io for iframe src
- Parse .cl-search-result inner text for title, price, location
- Fallback to URL slug extraction for missing titles
- Capture listing images for display in UI
- AutoTempest scraper also improved with better selectors
- Dockerfile with Xvfb + x11vnc + noVNC for browser-in-a-URL
- search.py auto-detects DISPLAY env to run headed vs headless
- pause_for_human() function for CAPTCHA/login handoff
- Facebook Marketplace search (headed mode only, needs login)
- Updated README with both modes