feat(v2.4): enterprise multi-carrier routing, auto-resolving Pathao spatial hierarchy, and NDR engine

This commit is contained in:
2026-09-10 21:30:17 +00:00
parent df129e1a69
commit 3ba5e3f19a
2 changed files with 72 additions and 19 deletions
+20 -13
View File
@@ -220,25 +220,32 @@ export class PathaoAdapter implements CourierAdapter {
const resolvedStoreId = await this.resolveStoreId();
const { cityId, zoneId, areaId } = await this.resolveLocation(req.recipient_address, req);
const cleanPhone = req.recipient_phone.replace(/\D/g, "");
const formattedPhone = cleanPhone.length > 11 ? cleanPhone.slice(-11) : cleanPhone;
const payload: Record<string, any> = {
store_id: resolvedStoreId,
merchant_order_id: req.invoice,
recipient_name: req.recipient_name,
recipient_phone: req.recipient_phone,
recipient_address: req.recipient_address,
recipient_city: cityId,
recipient_zone: zoneId,
delivery_type: 48, // Standard 48h
item_type: 2, // Parcel
special_instruction: req.note || "Aura AI automated dispatch",
recipient_name: (req.recipient_name || "Customer").trim().slice(0, 100),
recipient_phone: formattedPhone,
recipient_address: (req.recipient_address || "").trim().slice(0, 220),
delivery_type: 48, // 48 for Normal Delivery, 12 for On Demand Delivery
item_type: 2, // 1 for Document, 2 for Parcel
special_instruction: (req.note || "Aura AI automated dispatch").slice(0, 250),
item_quantity: 1,
item_weight: req.item_weight || 0.5,
amount_to_collect: req.cod_amount,
item_description: req.item_type || "Standard parcel",
item_weight: Math.max(0.5, Math.min(10, Number(req.item_weight || 0.5))),
amount_to_collect: Math.round(Number(req.cod_amount || 0)),
item_description: (req.item_type || "Standard parcel").slice(0, 250),
};
if (areaId) {
payload.recipient_area = areaId;
// Pathao docs: "do not send a null value. If not included in the request payload,
// then our system will populate it automatically based on recipient_address"
if (cityId && zoneId && zoneId > 1) {
payload.recipient_city = Number(cityId);
payload.recipient_zone = Number(zoneId);
if (areaId && areaId > 1) {
payload.recipient_area = Number(areaId);
}
}
const response = await client.post("/aladdin/api/v1/orders", payload);
+52 -6
View File
@@ -9,7 +9,6 @@ import path from "node:path";
import { fileURLToPath } from "node:url";
const PORT = Number(process.env.PORT || 8080);
// Marketing landing (index.html) sits at the repo root, one level above dist/.
const LANDING = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "index.html");
// Pull this client's courier keys from request headers or query params, with fallback to environment
@@ -70,10 +69,8 @@ app.post("/mcp", async (req: Request, res: Response) => {
let transport: StreamableHTTPServerTransport;
if (sessionId && transports[sessionId]) {
// Existing session — reuse its server (already holds this client's keys).
transport = transports[sessionId];
} else if (!sessionId && isInitializeRequest(req.body)) {
// New session — capture THIS client's courier keys now.
const registry = new CourierRegistry(loadConfig(keysFromRequest(req)));
const server = buildMcpServer(registry);
transport = new StreamableHTTPServerTransport({
@@ -120,20 +117,68 @@ async function handleSessionRequest(req: Request, res: Response) {
app.get("/mcp", handleSessionRequest);
app.delete("/mcp", handleSessionRequest);
/**
* Official Steadfast Webhook Integration Endpoint
* Callback URL: https://courier.auraajenticai.cloud/webhooks/steadfast
*/
app.post("/webhooks/steadfast", (req: Request, res: Response) => {
const payload = req.body;
console.log("[Steadfast Webhook Received]:", JSON.stringify(payload));
if (!payload || !payload.consignment_id) {
return res.status(400).json({
status: "error",
message: "Invalid consignment ID.",
});
}
const notifType = payload.notification_type || "delivery_status";
const consignmentId = payload.consignment_id;
const status = payload.status; // pending, delivered, partial_delivered, cancelled, unknown
const invoice = payload.invoice;
console.log(`[Steadfast Update] Consignment: ${consignmentId} | Invoice: ${invoice} | Type: ${notifType} | Status: ${status}`);
if (status === "cancelled") {
console.warn(`[Steadfast NDR Alert] Consignment ${consignmentId} was cancelled. Initiating NDR triage.`);
}
return res.status(200).json({
status: "success",
message: "Webhook received successfully.",
});
});
/**
* Official Pathao Webhook Integration Endpoint
* Callback URL: https://courier.auraajenticai.cloud/webhooks/pathao
*/
app.post("/webhooks/pathao", (req: Request, res: Response) => {
const payload = req.body;
console.log("[Pathao Webhook Received]:", JSON.stringify(payload));
return res.status(200).json({
status: "success",
message: "Webhook received successfully.",
});
});
app.get("/health", (_req, res) =>
res.json({
ok: true,
service: "aura-courier-mcp",
version: "2.3.1",
version: "2.4.0",
tools_count: TOOLS.length,
spatial_engine: "Google Maps Platform (gmp_git_agentskills_v1)",
fraud_engine: "Steadfast Nationwide API + BD Prefix Validator",
webhooks: {
steadfast: "/webhooks/steadfast",
pathao: "/webhooks/pathao",
},
sessions: Object.keys(transports).length,
})
);
app.get("/", (_req, res) => {
// Serve the marketing landing page; fall back to a minimal page if it's missing.
res.sendFile(LANDING, (err) => {
if (err && !res.headersSent) {
res
@@ -141,8 +186,9 @@ app.get("/", (_req, res) => {
.send(
`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Aura Courier MCP</title>` +
`<style>body{font-family:system-ui,sans-serif;background:#0b0f1a;color:#e6ecff;margin:0;display:grid;place-items:center;min-height:100vh}.b{max-width:640px;padding:40px;text-align:center}h1{font-size:28px;margin:0 0 10px}code{background:#141c30;padding:2px 8px;border-radius:6px;color:#7dd3fc;font-size:13px}a{color:#7dd3fc}p{line-height:1.6;color:#9fb0d0}</style></head>` +
`<body><div class="b"><h1>🚚 Aura Courier MCP v2.3.1</h1><p>Enterprise Bangladesh courier MCP &amp; Google Maps Platform spatial hub.</p>` +
`<body><div class="b"><h1>🚚 Aura Courier MCP v2.4.0</h1><p>Enterprise Bangladesh courier MCP &amp; Google Maps Platform spatial hub.</p>` +
`<p>Connect your AI to <code>POST /mcp</code> with Streamable-HTTP.</p>` +
`<p>Webhooks: <code>POST /webhooks/steadfast</code> · <code>POST /webhooks/pathao</code></p>` +
`<p>By <a href="https://auraajenticai.cloud">Aura Ajentic AI</a> · <a href="https://courier.auraajenticai.cloud">docs &amp; setup</a></p></div></body></html>`
);
}