D
Engineering

Conventions

Pola dominan adalah fat controller + domain services. Mongoose model sebagai ODM layer. Prompt Markdown di prompt/ adalah runtime configuration. ES modules. Tidak ada standardisasi response shape.

engine-bot memakai fat controller + domain services pattern. Controller (mainController.js) menangani buffer, dedup, context, orchestration, response, dan scheduling. Domain logic di service/ dan tools/ menangani query, formatting, dan external API.

Struktur direktori

text
app.js                  # Express + Socket.IO + MongoDB + Redis health
routes/chatbotRoutes.js # Semua endpoint /api
controllers/            # 5 file — mainController, aiAgent, product, address, webhook
middleware/             # authMiddleware
config/                 # env.js, db.js (gitignored)
models/                 # 24 Mongoose schema
service/                # 15 domain service — query, formatting, external API
subagents/              # 3 specialist agent — orders, payment, booking
tools/                  # 2 domain tools — order, booking
prompt/                 # Prompt Markdown — runtime configuration
scheduler/              # FollowUpMessages, workerService, worker
utils/                  # util.js (vision/transcription), redisHealth.js

Pola dominan — fat controller

controllers/mainController.js adalah entry point percakapan. Controller menangani:

text
1. verifyToken (middleware)        — auth
2. functionRouteBot                — validate store_id, customer_id, agent_id
3. dedup (in-memory map)           — 10 detik, key customer_id
4. userBuffer (message batching)   — based on time_reply
5. context loader                  — customer, agent, store, history, active order
6. intent detector                 — service/intent.js
7. main orchestrator               — prompt/main-agent.md + OpenAI
8. specialist agent                — subagents/*.js + tools
9. response formatter              — JSON, image extraction
10. follow-up scheduler             — scheduler/workerService.js (optional)

Domain service — service/

Service menangani query MongoDB, formatting, dan external API:

FileFungsi
service/chatbot.jsOrchestration helper
service/conversationsEmbed.jsConversation embedding
service/createVdb.jsVector DB creation (FAISS)
service/ragVdb.jsRAG retrieval
service/intent.jsIntent detection
service/product.jsProduct query + formatting
service/order.jsOrder lifecycle + checkout
service/carts.jsCart query
service/ongkir.jsRajaOngkir shipping cost + tracking
service/address.jsAddress parse + format
service/prompt.jsPrompt loading + context injection
service/costOpenAi.jsToken cost tracking
service/devices.jsDevice query
service/getCartsId.jsCart ID helper

Specialist agent — subagents/

FileAgentModelFungsi
subagents-orders.jsCustomer service, admin, logisticsgpt-4o-mini / gpt-5.4FAQ, cart, checkout, shipping
subagents-payment.jsPaymentgpt-5.4Metode bayar, konfirmasi, instant payment
subagents-booking.jsBookinggpt-4o-miniReservasi event — stub
subagents/payment/Payment tools—Detail tool payment

Domain tools — tools/

FileFungsi
tools/order/tools.jsCart, checkout, address, shipping, payment, complaint
tools/booking/tools.jsBooking — mengembalikan pesan belum diimplementasikan

Prompt — runtime configuration

Prompt Markdown di prompt/ adalah runtime configuration, bukan dokumentasi yang bisa dihapus:

PromptFungsi
prompt/main-agent.mdRouting dan final JSON response — main orchestrator
prompt/order/customer-service.mdProduct, FAQ, complaint
prompt/order/admin.mdCart dan checkout
prompt/order/logistics-agent.mdAddress, ongkir, courier, tracking
prompt/order/payment.mdPayment method, confirmation, status
prompt/booking/booking.mdBooking flow — backend stub

Agent-specific prompt digabung dengan dynamic context melalui promptWithContext.

Response shape

Tidak ada standardisasi — shape berbeda per controller:

json
// Chatbot reply normal (POST /api/chatbot-api)
{
  "statusCode": 201,
  "idUser": "customer_id",
  "idAgent": "agent_id",
  "idStore": "store_id",
  "data": {
    "answer": ["Balasan chatbot"],
    "images": [],
    "history": []
  }
}

// Welcome (POST /api/generate_welcome)
{
  "status": 201,
  "message": "success",
  "data": { "welcome_message": "...", "cost_request": "$0.000000" }
}

// Auth smoke test (GET /api/test)
{ "message": "berhasil" }

// Notify (POST /api/notify-new-message)
"Notification send to client"

ES modules

package.json memakai "type": "module". Semua import memakai import/export, bukan require. Path import wajib sertakan .js extension.

Logging

Log ad-hoc via console.log/console.error — tidak ada structured logger. Prefix [...] digunakan untuk konteks:

PrefixMakna
[Guard]Dedup request
[FastPath]Direct shipping cost path
[MAIN_ORCHESTRATOR]Main agent invocation
[ADMIN_AGENT]Cart/order agent
[SUBAGENT_PAYMENT]Payment agent
[INSTANT_PAYMENT]Checkout creation
[FollowUp]Scheduling
[WORKER]Job processing
[WEBHOOK_PAYMENT]Payment callback

Mongoose schema — inkonsistensi

MasalahLokasiDampak
require vs requiredmodels/orders.js banyak fieldTypo — validasi tidak aktif
payment_method duplikatmodels/orders.js:203 dan :255Mongoose ambil yang terakhir
Orders vs ordersNama model capitalMongoose auto-pluralize — verifikasi collection name
js
// service/myFeature.js
import MyModel from '../models/myModel.js';

export async function doSomething(storeId, customerId) {
  return await MyModel.find({ store_id: storeId, customer_id: customerId });
}

Daftarkan di controller atau tool yang relevan. Selalu sertakan store_id di query.

Anti-pola yang sering muncul

  1. Query tanpa store_id — bocor antar-merchant. Lihat Multi-tenant.
  2. Kredensial hardcoded di config/env.js — lihat Environment.
  3. x-forwarded-for dipercaya untuk IP allowlist — lihat Auth & JWT.
  4. Socket.IO tanpa auth/tenant room — lihat Tech Debt.
  5. Prompt Markdown sebagai kontrak — perubahan prompt mengubah perilaku agent tanpa code change.

Langkah berikutnya