暫無描述

Maciek 63ae1a2af9 Handle numeric Chatwoot message types in translation 3 周之前
docker e09111b4d2 Keep dev dependencies in the container so it can compile at start 4 周之前
docs 8783c1267f Add Chatwoot agent translation tools 3 周之前
flowise-tools 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
prisma 8783c1267f Add Chatwoot agent translation tools 3 周之前
public 891eba0b14 Refine Chatwoot translation workflow 3 周之前
scripts 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
src 63ae1a2af9 Handle numeric Chatwoot message types in translation 3 周之前
tests 63ae1a2af9 Handle numeric Chatwoot message types in translation 3 周之前
wp-plugins 59a6e501b4 Wielojęzykowość poprawna - system gotowy do głębszych testów i edge case 6 月之前
.env.example 63283506ae Tighten Chatwoot bot assignment and translation UI 3 周之前
.gitignore 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
Dockerfile e09111b4d2 Keep dev dependencies in the container so it can compile at start 4 周之前
README.md 15f4c29a8a Add ticket audit fixes and read-only ops panel 4 周之前
docker-compose.studio.yml 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
docker-compose.yml 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
package-lock.json 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
package.json 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
tsconfig.check.json 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前
tsconfig.json 7fe0ea23e8 Rewrite EKSRelay as a Node.js/TypeScript service 4 周之前

README.md

EKS Support Relay

Integration hub between Chatwoot (support inbox), Flowise (AI agent), WooCommerce and the WordPress eksrelay/v1 Store API for the EasyKlima support system.

Version 2 is a Node.js/TypeScript rewrite of the original PHP relay. The PHP implementation remains reachable in git history — see Migration.

What it does

customer e-mail
      │
      ▼
  Chatwoot  ──webhook message_created──▶  EKS Relay  ──▶  Flowise (Tool Agent)
      ▲                                     │  ▲               │
      │                                     │  └── /tools/* ───┘
      └────────── outgoing reply ───────────┘
                  or ticket handoff
  1. Chatwoot posts message_created to POST /webhooks/chatwoot.
  2. The relay validates, deduplicates and queues the event, then answers 202.
  3. A worker checks ticket mode, runs the spam gate, and calls Flowise.
  4. The agent may call back into /tools/* for live shop data.
  5. The answer is posted back to Chatwoot, or the conversation is handed off to a human with a ticket number.

Endpoints

Method Path Auth Purpose
GET /health Liveness. No dependencies touched.
GET /ready Readiness plus per-dependency status. No secrets.
POST /webhooks/chatwoot Chatwoot message_created intake.
POST /tools/get_order_data Bearer Order lookup with e-mail ownership check.
POST /tools/get_product_data Bearer Product by id / SKU / search.
POST /tools/get_shipping_data Bearer Zones, or per-zone methods and costs.
POST /tools/get_payment_methods Bearer Enabled payment gateways.
POST /tools/get_product_compatibility Bearer Car ↔ product compatibility.
POST /tools/get_car_data Bearer Brands / models / engines.
POST /tools/new_ticket Bearer Create (or reuse) a ticket, hand off.
GET /ops Read-only operations panel shell; data still requires ADMIN_TOKEN in the browser.
GET /admin/events Bearer (admin) Recent audit trail; filters: conversationId, eventType, limit.
GET /admin/jobs Bearer (admin) Queue stats and jobs; filters: status, limit.
GET /admin/messages Bearer (admin) Processed-message/idempotency records; filters: conversationId, status, limit.
GET /admin/tickets Bearer (admin) Ticket records with last event/skipped-message counters.
GET /admin/meta Bearer (admin) Non-secret counters/settings for the ops panel.

/tools/* uses Authorization: Bearer <RELAY_SHARED_SECRET>. /admin/* uses Authorization: Bearer <ADMIN_TOKEN>; when ADMIN_TOKEN is empty the admin routes are closed, not open.

Architecture

src/
  config.ts                 zod-validated environment contract
  logger.ts                 JSON logger + secret/PII redactor
  errors.ts                 RelayError (http code + stable error code)
  clients/
    httpClient.ts           fetch wrapper: timeouts, safe labels
    chatwootClient.ts       conversations, labels, attributes, messages
    flowiseClient.ts        prediction call + response normalisation
    wooClient.ts            WooCommerce REST v3, WPML search fallbacks
    wpStoreClient.ts        eksrelay/v1 mu-plugin endpoints
  domain/
    messageNormalizer.ts    Chatwoot payload → SupportMessageEvent
    spamGate.ts             bounce / autoreply / newsletter filtering
    ticketService.ts        ticket numbering + idempotent handoff
    conversationPipeline.ts the single decision path per message
    storeLocales.ts         language → currency with shop-aware fallback
    formatters.ts           curated order/product views for the agent
  queue/
    jobQueue.ts             DB-backed queue with retry/backoff
    worker.ts               in-process poller
  store/
    db.ts                   Prisma client
    idempotencyStore.ts     ProcessedMessage claim/status
    auditLog.ts             redacted audit events
  http/                     express app, routes, middleware

Channel adapters are the extension point: any new channel only has to produce a SupportMessageEvent, and the whole AI/ticket/spam pipeline applies unchanged.

Persistence

SQLite via Prisma (prisma/schema.prisma):

  • ProcessedMessage — idempotency guard, unique on (source, messageId).
  • Job — queued work with attempts, lastError (redacted), backoff.
  • Ticket — one row per conversation, unique on conversationId.
  • AuditEvent — redacted decision trail.

Browsing the database

# On the server: start Prisma Studio bound to localhost only,
# then reach it through an SSH tunnel.
ssh -i <key> -L 5555:127.0.0.1:5555 ubuntu@<host>
docker compose -f docker-compose.yml -f docker-compose.studio.yml up -d studio
# open http://127.0.0.1:5555 — stop it again when done
docker compose -f docker-compose.yml -f docker-compose.studio.yml down

Locally: npm run db:studio.

Prisma Studio has full read/write access and must never be exposed publicly.

Local development

npm install
cp .env.example .env        # fill in real values, chmod 600
export DATABASE_URL="file:../data/eks_relay.db"
npx prisma migrate deploy
npm run dev                 # tsx watch
npm run lint     # tsc type-check over src, tests and scripts
npm test         # node:test suite
npm run build    # compile to dist/
npm run events   # CLI audit-trail viewer

Docker

docker compose config       # validate
docker compose up -d --build
docker compose ps
docker compose logs -f relay

The repository is bind-mounted into the container and the entrypoint installs, generates and migrates on start, so a code change needs a restart, not a rebuild:

git pull && docker compose restart relay

With RELAY_MODE=dev the container runs tsx watch, so edits are picked up without even a restart. RELAY_MODE=prod compiles once and runs dist/.

A rebuild is only needed when the base image or system packages change.

Configuration

See .env.example for every variable with inline notes. Boot fails loudly with the offending variable names (never their values) when the environment is incomplete.

Logging

Structured JSON on stdout/stderr. Secrets (tokens, bearer headers, Woo consumer keys, credentialed query strings) are always redacted. PII (customer e-mail, names, message bodies) is redacted unless LOG_PII=true, which is meant for temporary debugging only.

Documentation

Migration from the PHP relay

The PHP implementation lived in src/ and public/ until the v2 rewrite. It is preserved at the php-legacy tag and stays deployed on the EasyKlima web server as a fallback until the Node relay has passed a real e-mail test. See docs/MIGRATION.md.

Flowise tools

flowise-tools/*.json holds the exported custom-tool definitions. The relay's response contracts are built to match them exactly — changing a response shape means updating the corresponding tool in Flowise as well.

WordPress plugin

wp-plugins/eksrelay_api.php is the mu-plugin providing eksrelay/v1. It is deployed to the shop's WordPress, not to this service.