update on the agents and registry side
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
// ==============================|| Skill: Rider Battery & Device Safety ||============================== //
|
||||
|
||||
const OPEN_STATUSES = new Set(['pending', 'accepted', 'arrived', 'picked', 'active', 'skipped']);
|
||||
const isOpen = (row) => OPEN_STATUSES.has(String(row?.orderstatus || '').toLowerCase());
|
||||
const ref = (row) => row?.orderid || row?.bookingno || (row?.bookingid ? `#${row.bookingid}` : '—');
|
||||
|
||||
export const RiderBatterySafetySkill = {
|
||||
id: 'skill_rider_battery_safety',
|
||||
name: 'Rider Device & SOS Safety',
|
||||
description: 'Monitors rider device telemetry to prevent unreachability due to low battery during active deliveries.',
|
||||
category: 'rider_safety',
|
||||
icon: 'BatteryWarning',
|
||||
// OFF by default (2026-09-29): the rows this rule reads carry no battery level: it lives on the rider profile (milerprofiles.batterypercentage), not on booking rows.
|
||||
// Enabled, it would read undefined on every row and report an all-clear board —
|
||||
// the silent failure normalise.js warns about. Turn it on only once the data exists.
|
||||
dataGap: 'no battery level: it lives on the rider profile (milerprofiles.batterypercentage), not on booking rows',
|
||||
defaultEnabled: false,
|
||||
|
||||
thresholds: {
|
||||
criticalBatteryPercent: {
|
||||
label: 'Critical Battery Level (%)',
|
||||
description: 'Threshold below which rider device is considered at risk of shutdown.',
|
||||
value: 15,
|
||||
min: 5,
|
||||
max: 30,
|
||||
step: 5,
|
||||
unit: '%'
|
||||
}
|
||||
},
|
||||
|
||||
instructions: `
|
||||
- When a rider has critical battery while carrying in-transit orders, advise charging or offloading remaining pending pickups.
|
||||
`,
|
||||
|
||||
tools: [
|
||||
{
|
||||
name: 'alert_low_battery_rider',
|
||||
description: 'Notifies rider to connect portable charger or report to nearest hub.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
milerId: { type: 'number', description: 'Target miler user ID' }
|
||||
},
|
||||
required: ['milerId']
|
||||
},
|
||||
handler: async (args) => ({
|
||||
success: true,
|
||||
proposal: {
|
||||
action: 'battery_alert',
|
||||
milerId: args.milerId,
|
||||
blastRadius: `Sends device power warning notification to Rider #${args.milerId}.`
|
||||
}
|
||||
})
|
||||
}
|
||||
],
|
||||
|
||||
evaluate: (rows = [], now, currentThresholds = {}) => {
|
||||
const minBattery = currentThresholds.criticalBatteryPercent ?? 15;
|
||||
const safeRows = Array.isArray(rows) ? rows : [];
|
||||
|
||||
const atRisk = safeRows.filter((r) => {
|
||||
if (!isOpen(r) || !r.userid) return false;
|
||||
const battery = Number(r.battery_percentage || r.battery_level || r.battery || 100);
|
||||
return battery > 0 && battery <= minBattery;
|
||||
});
|
||||
|
||||
if (!atRisk.length) return [];
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'rider_critical_battery',
|
||||
skillId: 'skill_rider_battery_safety',
|
||||
severity: 'warning',
|
||||
title: `${atRisk.length} active delivery under low rider device battery (≤ ${minBattery}%)`,
|
||||
why: `Rider phone is nearing shutdown, risking lost GPS telemetry and customer communication failure.`,
|
||||
count: atRisk.length,
|
||||
rows: atRisk,
|
||||
detail: atRisk.slice(0, 8).map((r) => {
|
||||
const bat = r.battery_percentage || r.battery_level || r.battery || 'Low';
|
||||
return `${ref(r)} — ${r.ridername || 'Rider'} (${bat}% battery)`;
|
||||
}),
|
||||
proposal: {
|
||||
label: 'Send power alert',
|
||||
tool: 'alert_low_battery_rider',
|
||||
scope: atRisk,
|
||||
blastRadius: 'Sends charging prompt to rider.'
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user