update on the agents and registry side

This commit is contained in:
2026-09-30 12:03:13 +05:30
parent 92e8da2842
commit 53199127ba
73 changed files with 7268 additions and 1134 deletions

View File

@@ -0,0 +1,105 @@
// ==============================|| Skill: Hub Congestion Agent ||============================== //
//
// Detects parcels that have been sitting at a hub for too long without
// being picked up by a rider. These represent blocked capacity at the hub
// and direct SLA risk for the customer. This is critical for hub operations
import { parseDoormileTimestamp } from '@/lib/doormileTimestamp';
const HUB_STATUSES = new Set(['pending', 'accepted']); // at hub, not yet picked
const minutesBetween = (from, to) => {
const a = parseDoormileTimestamp(from);
const b = parseDoormileTimestamp(to);
if (!a.isValid() || !b.isValid()) return null;
return b.diff(a, 'minute');
};
const ref = (row) => row?.orderid || row?.bookingno || (row?.bookingid ? `#${row.bookingid}` : '—');
export const HubCongestionSkill = {
id: 'skill_hub_congestion',
name: 'Hub Congestion Agent',
description: 'Detects parcels sitting at a hub without rider pickup beyond the dwell threshold. Dispatches nearest idle rider.',
category: 'sla_management',
icon: 'ShieldAlert',
defaultEnabled: true,
thresholds: {
hubDwellMinutes: {
label: 'Hub Dwell Threshold',
description: 'Minutes a parcel can sit at hub without a rider pickup before raising a congestion alert.',
value: 45,
min: 15,
max: 120,
step: 5,
unit: 'min'
}
},
instructions: `
- Parcels sitting at a hub beyond the dwell threshold block capacity for the next batch.
- Identify the nearest idle rider in the same zone and dispatch immediately.
- Prefer riders with the fewest active orders to avoid overloading.
`,
tools: [
{
name: 'dispatch_hub_idle_parcels',
description: 'Proposes dispatching a nearby idle rider to collect stalled hub parcels.',
parameters: {
type: 'object',
properties: {
hubId: { type: 'string', description: 'Hub identifier where parcels are stalled' },
bookingIds: { type: 'array', items: { type: 'number' }, description: 'Booking IDs to dispatch' },
milerId: { type: 'number', description: 'Target idle rider user ID' }
},
required: ['bookingIds']
},
handler: async (args) => ({
success: true,
proposal: {
action: 'dispatch_hub_parcels',
hubId: args.hubId || 'unknown',
bookingIds: args.bookingIds,
milerId: args.milerId,
blastRadius: `Dispatches rider to collect ${args.bookingIds?.length || 'stalled'} parcel(s) from hub. Updates parcel status to In-Transit.`
}
})
}
],
evaluate: (rows = [], now, currentThresholds = {}) => {
const dwellLimit = currentThresholds.hubDwellMinutes ?? 45;
const findings = [];
const stalled = rows
.filter((r) => HUB_STATUSES.has(String(r?.orderstatus || '').toLowerCase()))
.map((r) => ({ row: r, dwellMin: minutesBetween(r.orderdate, now) }))
.filter((m) => m.dwellMin !== null && m.dwellMin >= dwellLimit)
.sort((a, b) => b.dwellMin - a.dwellMin);
if (stalled.length) {
findings.push({
id: 'hub_parcel_stalled',
skillId: 'skill_hub_congestion',
severity: 'critical',
title: `${stalled.length} parcel${stalled.length === 1 ? '' : 's'} stalled at hub for >${dwellLimit}m`,
why: 'Parcel has been at the hub beyond the acceptable dwell time with no rider assigned for pickup.',
count: stalled.length,
rows: stalled.map((m) => m.row),
detail: stalled.slice(0, 8).map((m) => `${ref(m.row)} — at hub for ${m.dwellMin} min`),
proposal: {
label: 'Dispatch idle rider to hub',
tool: 'dispatch_hub_idle_parcels',
scope: stalled.map((m) => m.row),
blastRadius: 'Assigns nearest idle zone rider to collect and dispatch all stalled parcels.'
}
});
}
return findings;
}
};