Open
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.