|
|
3 semanas atrás | |
|---|---|---|
| docker | 3 semanas atrás | |
| docs | 3 semanas atrás | |
| flowise-tools | 3 semanas atrás | |
| prisma | 3 semanas atrás | |
| public | 3 semanas atrás | |
| scripts | 3 semanas atrás | |
| src | 3 semanas atrás | |
| tests | 3 semanas atrás | |
| wp-plugins | 6 meses atrás | |
| .env.example | 3 semanas atrás | |
| .gitignore | 3 semanas atrás | |
| Dockerfile | 3 semanas atrás | |
| README.md | 3 semanas atrás | |
| docker-compose.studio.yml | 3 semanas atrás | |
| docker-compose.yml | 3 semanas atrás | |
| package-lock.json | 3 semanas atrás | |
| package.json | 3 semanas atrás | |
| tsconfig.check.json | 3 semanas atrás | |
| tsconfig.json | 3 semanas atrás |
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.
customer e-mail
│
▼
Chatwoot ──webhook message_created──▶ EKS Relay ──▶ Flowise (Tool Agent)
▲ │ ▲ │
│ │ └── /tools/* ───┘
└────────── outgoing reply ───────────┘
or ticket handoff
message_created to POST /webhooks/chatwoot.202./tools/* for live shop data.| 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.
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.
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.# 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.
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 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.
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.
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.
docs/DEPLOY.md — server layout, Traefik, Cloudflare, updates.docs/SMOKE_TEST.md — the verification runbook.docs/MIGRATION.md — PHP → Node differences and fallback.docs/TODO.md — known follow-ups, including safe production-mailbox cutover.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/*.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.
wp-plugins/eksrelay_api.php is the mu-plugin providing eksrelay/v1. It is
deployed to the shop's WordPress, not to this service.