Files
trade-assistant/AGENTS.md
T
TradeMate Dev 3e39cf0170 refactor: replace direct WeChat/Alipay with unified pay-api gateway
Switch from direct WeChat Pay / Alipay integrations to the unified
宇之然 pay-api gateway (HMAC-SHA256 auth). Removes wechat_pay.py,
keeps PaymentGateway abstraction, adds UnifiedPayService. Simplifies
payment.py create_order to {plan, pay_type} params. Single webhook
endpoint replaces separate WeChat/Alipay notify handlers.
2026-05-29 18:36:50 +08:00

5.7 KiB

TradeMate (外贸小助手) — Agent Guide

Architecture

  • Backend: backend/ — FastAPI + SQLAlchemy 1.4 async + asyncpg, single app.main:app
  • Frontends: uni-app/ (mobile H5/mini-program), admin-frontend/ (PC admin), user-frontend/ (PC workspace)
  • Config: backend/app/config.py reads from /.env (project root) via pydantic BaseSettings
  • Auth: JWT (python-jose). Default dep get_current_user_id in backend/app/api/v1/deps.py
  • AI Router: backend/app/ai/router.py — singleton AIRouter, DB-driven providers. Primary = sensenova, fallbacks = alibaba-mt / opencode_go / nvidia / spark
  • Database: PostgreSQL via asyncpg, pool_size=20

AI Providers

  • Active: Sensenova (商汤), OpencodeGo, NVIDIA, 讯飞 Spark, 阿里机器翻译 (alibaba-mt)
  • Removed (dead code): Claude (claude.py), DeepL (deepl.py), Local (local.py) — git rm'd, not yet committed
  • DB-driven: AIProvider model + admin_ai.py API — manage providers at runtime. router.seed_from_env() loads from .env on startup
  • Provider type mapping in router.py._build_provider(): sensenova, opencode_go, nvidia, spark, alibaba-mt

Security

  • CORS: middleware.py — whitelist origins, restricted methods/headers
  • Rate Limit: endpoint-specific — login 5/min, register 3/h, password 3/5min, payment 20/min, admin 30/min
  • CSRF: core/csrf.py — double-submit cookie pattern. Required on auth/payment/profile. Webhooks skipped.
  • Login: JSON LoginRequest model, not OAuth2PasswordRequestForm

Customer Discovery

  • discovery.py + discovery_record.py — Google Custom Search integration
  • Contact extraction from company websites (email/phone/WhatsApp/WeChat)

Dev Commands

# Backend (from project root — .env is there)
cd backend && source venv/bin/activate && uvicorn app.main:app --reload --port 8000

# Mobile H5
cd uni-app && npm run dev:h5

# Admin frontend (PC management)
cd admin-frontend && npm run dev   # port 5173, base: /admin/

# User workspace (PC workbench)
cd user-frontend && npm run dev    # port 5174, base: /workspace/

# Tests (backend — needs PostgreSQL running with foreign_trade_test DB)
cd backend && venv/bin/pytest              # all
venv/bin/pytest tests/test_auth_api.py     # single file
venv/bin/pytest tests/ -k "test_login"     # keyword filter

# Builds
cd uni-app && npm run build:h5             # uni-app (mobile H5)
cd admin-frontend && npm run build         # admin => /www/wwwroot/trade.yuzhiran.com/admin/
cd user-frontend && npm run build          # workspace => /www/wwwroot/trade.yuzhiran.com/workspace/

# Alembic migrations
cd backend && alembic upgrade head
alembic revision --autogenerate -m "desc"

Deployment

  • Landing page: trade.yuzhiran.com/ — static marketing HTML
  • SPA: trade.yuzhiran.com/app/ — uni-app build (mobile)
  • Admin: trade.yuzhiran.com/admin/ — Vue 3 + Element Plus (standalone)
  • Workspace: trade.yuzhiran.com/workspace/ — Vue 3 + Element Plus (standalone)
  • Nginx: SPA fallbacks for /app/, /admin/, /workspace/
  • vite config: each project has its own base path and dev port
  • API: proxied via nginx location /api/ to 127.0.0.1:8002

Critical Quirks

  • Route ordering: FastAPI matches top-down. Specific routes (/{customer_id}/health) must be registered before wildcard /{customer_id}.
  • AI extract_info: Some models (e.g. deepseek-v4-flash) don't support response_format={"type": "json_object"}. openai.py catches the failure and retries without it.
  • Manual auth on some endpoints: keywords and competitor-analysis endpoints use authorization: str = Header(None) instead of Depends(get_current_user_id).
  • MarketingService fallback: When no AI providers initialized, returns template content instead of crashing.
  • Onboarding service: calls mkt.generate(product_info={"name": ..., ...}), not keyword args. Check onboarding.py for the exact dict shape.
  • CustomerHealthService: get_health_overview endpoint must use CustomerHealthService(db) not CustomerService(db).
  • CSRF: Sensitive endpoints (auth/payment/profile) require X-CSRF-Token header. Token available via csrf_token cookie / X-CSRF-Token response header.
  • AI Router reload: After modifying AI providers via admin API, call POST /api/v1/admin/ai/reload to refresh in-memory providers.
  • Payment: Uses unified pay-api gateway (UnifiedPayService). NOT direct WeChat/Alipay integration. Credentials: PAY_API_KEY/PAY_API_SECRET from .env. HMAC-SHA256 auth. Webhook at POST /api/v1/payment/webhook skips CSRF.
  • Payment gateway config: PAY_API_KEY, PAY_API_SECRET, PAY_API_BASE_URL, PAY_WEBHOOK_URL in config.py. pay_type param: "alipay" (returns pay_url) or "wechat" (returns code_url). UnifiedPayService normalizes legacy native/jsapi/pc to wechat/alipay.

Project Conventions

  • No README.md — key context is in PROGRESS.md and docs/
  • Chinese UI — mobile-first, for foreign-trade SOHOs/small teams
  • No comments in code unless explicitly asked
  • Commit messages focus on "why" not "what", in English
  • Services instantiate MarketingService() (no db needed). For customer health: CustomerHealthService(db)
  • AI providers in backend/app/ai/providers/ — inherit from OpenAIProvider if compatible with OpenAI API format
  • Static assets go in uni-app/src/static/
  • Test DB: foreign_trade_test (uses credentials from conftest.py, not .env)

Remember

  • Write tests for new features
  • Run cd backend && venv/bin/pytest before committing
  • Keep context compact — avoid bloating the session with unnecessary file reads