Skip to content

Comments

Feature/stats page and offers#147

Open
yousifalsatari wants to merge 22 commits intomoltbook:mainfrom
SaiPaladugu:feature/stats-page-and-offers
Open

Feature/stats page and offers#147
yousifalsatari wants to merge 22 commits intomoltbook:mainfrom
SaiPaladugu:feature/stats-page-and-offers

Conversation

@yousifalsatari
Copy link

No description provided.

SaiPaladugu and others added 22 commits February 11, 2026 11:32
Complete refactor of Moltbook API into an AI marketplace with:

Commerce domain:
- stores, products, listings, offers, orders, reviews
- strict purchase gating (interaction evidence required)
- private offers with public offer references
- trust profiles with reason-coded deltas
- patch notes on price/policy changes
- AI-generated product images (DALL-E via Shopify proxy)

Architecture:
- 12 SQL migrations with deferred FK constraints
- 9 commerce services + ImageGenService
- 13 commerce route files under /api/v1/commerce
- role enforcement (requireMerchant/requireCustomer)
- public read endpoints for observers (no auth)
- operator control surface with OPERATOR_KEY auth
- API key pool rotation on 429 rate limits

Agent runtime:
- LLM-driven action selection (provider-agnostic)
- deterministic fallback with balanced action distribution
- WorldStateService for minimal DB context reads
- quiet-feed failsafe for no-dead-air
- runtime_state table for worker/operator coordination

Testing:
- 76-test E2E suite (13 groups incl. privacy + role enforcement)
- concurrency race condition tests (16 tests)
- LLM chaos resilience tests (10 tests)
- soak test (configurable duration)
- smoke test, doctor script, seed script
- API contract snapshots
- CI workflow with Postgres service

Co-authored-by: Cursor <cursoragent@cursor.com>
- Dockerfile for API (schema + migrations + server)
- Dockerfile.worker for agent runtime process
- Production start script (auto-applies schema + migrations)
- .dockerignore for clean builds
- Live at https://moltbook-api-production.up.railway.app

Co-authored-by: Cursor <cursoragent@cursor.com>
Root cause: agents were stuck in create/browse loop because:
1. One-listing-per-store constraint blocked merchants from selling
2. LLM had no memory of what each agent already did
3. Prompt was a priority list, not a lifecycle

Fixes:
- Drop one_active_listing_per_store constraint (migration 013)
- Add WorldStateService.getAgentContext() with personal context
  (unlisted products, pending offers, purchase eligibility, etc.)
- Rewrite LLM prompt as lifecycle guidance (ask->offer->buy->review)
- Rewrite deterministic fallback with same lifecycle logic
- Pass agent-specific context to LLM so it knows "your next step"

Result: agents now negotiate, purchase, review, and argue instead
of just creating products and asking questions.

Co-authored-by: Cursor <cursoragent@cursor.com>
…BASE_URL

Co-authored-by: Cursor <cursoragent@cursor.com>
- Move image storage to GCS (gs://moltbook-images-hd) so worker (VM)
  and API (Cloud Run) share images. API proxies from GCS with local fallback.
- Add worker heartbeat: updates runtime_state.updated_at each tick.
- Add /api/v1/health/deep endpoint with worker status, DB, and entity counts.
- Add scripts/monitor.js for cron-based Slack alerting on stale heartbeat.
- Install @google-cloud/storage dependency.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Agent selection: 50% bias toward agents with pending work (unreviewed
  orders, pending offers, eligible purchases) to progress the lifecycle
- Merchant fallback: 30% create_product, 15% update_price, 25% reply,
  30% thread engagement. Realistic offer rejection (~45% reject rate).
- Customer fallback: 25% ask, 25% offer, 25% purchase, 20% reply, 5%
  looking-for. Removed LOOKING_FOR as catch-all default.
- Quiet-feed failsafe: increased threshold from 30s to 5 minutes, uses
  varied actions instead of always creating LOOKING_FOR threads.
- LLM prompts: explicit weight guidance for each action type, stronger
  emphasis on catalog expansion and price updates for merchants, and
  lifecycle progression for customers.

Co-authored-by: Cursor <cursoragent@cursor.com>
The LLM never picks create_product on its own, starving the marketplace.
Add _supplyCheck that fires 20% of ticks and forces merchants to:
- List unlisted products (highest priority)
- Update prices on existing listings (40% of supply checks)
- Create new products (60% of supply checks)

This ensures steady catalog growth independent of LLM behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Images behind IAP can't be loaded by <img> tags cross-origin.
Instead of relative /static/ paths, the API now returns time-limited
signed GCS URLs directly in listing and product image responses.

- Add getSignedUrl() and resolveImageUrl() to ImageGenService
- Listings endpoints auto-resolve primary_image_url to signed URLs
- Products /images endpoint auto-resolves all image_url fields
- Signed URLs valid for 1 hour, direct GCS access (no IAP needed)

Co-authored-by: Cursor <cursoragent@cursor.com>
…ssion

resolveImageUrl was crashing the entire endpoint when getSignedUrl
failed (missing iam.serviceAccountTokenCreator on Cloud Run SA).
Now falls back to relative /static/ path gracefully.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
New script: scripts/gcp-validate.js
- Tests all 72 API endpoints against live Cloud SQL + GCS
- 6 phases: public reads, agent-auth reads, image pipeline,
  commerce lifecycle, operator endpoints, negative/edge cases
- Validates GCS signed URLs (or /static/ fallback) with actual
  image fetch and PNG content-type verification
- Full commerce lifecycle: register → store → product → listing
  → question → offer → accept → purchase → review
- Auth enforcement: 401/403/404/400 edge cases

Also fixes:
- PostService.getPersonalizedFeed: DISTINCT + complex ORDER BY
  crash when agent has no subscriptions (SQL subquery fix)

Run: node scripts/gcp-validate.js
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Express proxies SSR pages to Next.js running on internal port 3001
- Static assets (_next/static/) served directly by Express (standalone
  mode doesn't serve them)
- API routes (/api/v1/*) and image proxy (/static/*) unaffected
- Both frontend and API share the same Cloud Run domain + IAP cookie
- Dockerfile updated to include frontend standalone build
- http-proxy-middleware added for clean SSR proxying

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…rontend deps

Co-authored-by: Cursor <cursoragent@cursor.com>
…relative

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants