upates on the toast and createorder and allthose things
This commit is contained in:
@@ -189,6 +189,9 @@ export const executeCreateCustomer = async (payload) => {
|
||||
return {
|
||||
ok: false,
|
||||
status,
|
||||
// The server's own reason, unformatted, for callers that word the
|
||||
// message themselves (the home page's plain-language toasts).
|
||||
serverMessage,
|
||||
message,
|
||||
sourceCalls: [
|
||||
{
|
||||
|
||||
168
src/lib/assistant/smalltalk.js
Normal file
168
src/lib/assistant/smalltalk.js
Normal file
@@ -0,0 +1,168 @@
|
||||
// ==============================|| MileTruth — greetings & "what can you do?" ||============================== //
|
||||
//
|
||||
// "good afternoon" used to reach the intent router, match nothing, and get
|
||||
// "I could not answer that from live data" — the first thing a new user typed
|
||||
// was answered with a failure. This module answers it instead: a greeting back,
|
||||
// then what the assistant can actually do, with examples that run when clicked.
|
||||
//
|
||||
// Deliberately narrow. A greeting only counts when it is the WHOLE message, or
|
||||
// the opening of one ("hi, how many orders today?") — then the greeting is
|
||||
// stripped and the question is answered normally. Nothing here touches data.
|
||||
//
|
||||
// Keep CAPABILITIES honest: list only what the home page really does. Every
|
||||
// example is sent as a real question when clicked, so a wrong one fails in
|
||||
// front of the user.
|
||||
|
||||
const GREETING_RE =
|
||||
/^\s*(?:(good\s*(?:morning|afternoon|evening|night|day))|(hi+|hello+|hey+|hiya|howdy|yo|namaste|vanakkam|greetings|gm|ge|ga))\b[\s,!.]*(?:(?:there|team|all|everyone|miletruth|mile\s*truth|ai|bot|assistant|buddy|friend|sir|madam)\b[\s,!.]*)?/i;
|
||||
|
||||
// ---- "What can you do?" -------------------------------------------------------
|
||||
//
|
||||
// Recognised by MEANING, not by an exact sentence. The first version listed
|
||||
// fixed phrasings, and "what are things you can do ?" — an ordinary way to
|
||||
// ask — wasn't one of them, so it got "Sorry, I didn't understand". People
|
||||
// word this question a hundred ways; the rules below look for its shape:
|
||||
// a question about YOU (the assistant) and what it does / offers / knows.
|
||||
//
|
||||
// Two guards keep real questions out:
|
||||
// • DOMAIN words (orders, riders, hubs, revenue …) mean it's an operations
|
||||
// question — "what can you tell me about orders today" goes to the router.
|
||||
// • Long messages (> 14 words) are never treated as small talk.
|
||||
|
||||
const DOMAIN_RE =
|
||||
/\b(?:orders?|bookings?|deliver(?:y|ies)|riders?|milers?|drivers?|hubs?|vehicles?|fleet|revenue|sales|profit|pricing|price|consignments?|parcels?|exceptions?|tripsheets?|customers?|clients?|tenants?|dispatch|batch|pincode|today|yesterday|week|month|dm-[a-z0-9-]+|\d{4,})\b/i;
|
||||
|
||||
// Exact short commands that mean "show me the menu".
|
||||
const MENU_RE =
|
||||
/^(?:help|help\s+me|menu|options|features|capabilities|commands|guide|start|get\s+started|how\s+are\s+you(?:\s+doing)?|what'?s\s+up|sup|what\s+now|now\s+what|anything\s+else|what\s+else)$/;
|
||||
|
||||
const CAPABILITY_PATTERNS = [
|
||||
// what (are the / all / kind of) things can you do · what do you do · what else can u help with
|
||||
/\b(?:what|wat|wht|which)\b.*\b(?:you|u|ya)\b.*\b(?:do|does|help|offer|handle|support|manage|provide|know|able)\b/,
|
||||
// what can I (ask / do / use) · what should I ask · what questions can I ask
|
||||
/\b(?:what|wat|which|how)\b.*\b(?:can|could|should|do)\b.*\b(?:i|we)\b.*\b(?:ask|do|use|say|type|try)\b/,
|
||||
// can you help me · can you do anything · are you able to help
|
||||
/^(?:can|could|will|would|are)\s+(?:you|u)\b.*\b(?:help|do|assist|able)\b/,
|
||||
// your features / abilities / skills / functions / commands
|
||||
/\b(?:your|ur)\b.*\b(?:features?|capabilit(?:y|ies)|abilit(?:y|ies)|skills?|functions?|commands?|uses?|job|purpose|role)\b/,
|
||||
// list / show / tell me (all) your features · show me what you can do
|
||||
/\b(?:list|show|tell|explain|give)\b.*\b(?:features?|capabilit(?:y|ies)|abilit(?:y|ies)|skills?|functions?|commands?|what\s+(?:you|u)\s+(?:can|do))\b/,
|
||||
// who / what are you · what is this (ai / bot / tool / thing / page) · what is miletruth
|
||||
/\bwho\b.*\b(?:are|r)\b.*\b(?:you|u)\b/,
|
||||
/\bwhat\b.*\b(?:is|are|'s)\b.*\b(?:you|u|this|miletruth|mile\s*truth)\b/,
|
||||
// how does this work · how do I use this / you · how to use · how to start
|
||||
/\bhow\b.*\b(?:does|do|to|can)\b.*\b(?:work|use|start|begin|get\s+started)\b/,
|
||||
// why should I use you · what are you for · what are you good at
|
||||
/\b(?:good\s+at|for\s+what|what\s+for|used\s+for)\b/
|
||||
];
|
||||
|
||||
const normalize = (text) =>
|
||||
String(text || '')
|
||||
.toLowerCase()
|
||||
.replace(/[’`]/g, "'")
|
||||
.replace(/[^a-z0-9' -]+/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
export const isCapabilitiesQuestion = (text) => {
|
||||
const t = normalize(text);
|
||||
if (!t) return false;
|
||||
if (MENU_RE.test(t)) return true;
|
||||
if (t.split(' ').length > 14) return false;
|
||||
if (DOMAIN_RE.test(t)) return false;
|
||||
return CAPABILITY_PATTERNS.some((re) => re.test(t));
|
||||
};
|
||||
|
||||
// Short courtesies with no question in them — answered with a short reply, not
|
||||
// the full capability list.
|
||||
const THANKS_RE = /^\s*(?:thanks?|thank\s+you|thx|ty|ok(?:ay)?|cool|great|nice|super|awesome|got\s+it)\b[\s!.]*(?:(?:so\s+much|a\s+lot|miletruth|mile\s*truth)\b[\s!.]*)?$/i;
|
||||
|
||||
const clockGreeting = (now) => {
|
||||
const h = now.getHours();
|
||||
if (h < 12) return 'Good morning';
|
||||
if (h < 17) return 'Good afternoon';
|
||||
return 'Good evening';
|
||||
};
|
||||
|
||||
/**
|
||||
* Splits a leading greeting off a message.
|
||||
* Returns { greeting, rest } — greeting is the phrase to answer with (null
|
||||
* when there wasn't one), rest is whatever followed it, trimmed.
|
||||
*/
|
||||
export const splitGreeting = (text, now = new Date()) => {
|
||||
const raw = String(text || '');
|
||||
const m = raw.match(GREETING_RE);
|
||||
if (!m) return { greeting: null, rest: raw.trim() };
|
||||
// Mirror the greeting the user chose ("good afternoon" → "Good afternoon",
|
||||
// "gm" → "Good morning"); answer a plain hi/hello by the clock.
|
||||
const ABBREVIATIONS = { gm: 'morning', ga: 'afternoon', ge: 'evening' };
|
||||
const part = m[1]
|
||||
? m[1].replace(/^good\s*/i, '').toLowerCase()
|
||||
: ABBREVIATIONS[String(m[2] || '').toLowerCase()];
|
||||
const greeting = part ? `Good ${part}` : clockGreeting(now);
|
||||
return { greeting, rest: raw.slice(m[0].length).trim() };
|
||||
};
|
||||
|
||||
export const isThanks = (text) => THANKS_RE.test(String(text || ''));
|
||||
|
||||
/** What the home page does, grouped, each with examples that run on click. */
|
||||
export const CAPABILITIES = [
|
||||
{
|
||||
title: 'Create & book',
|
||||
description: 'I collect the details step by step, and nothing is saved until you press confirm.',
|
||||
examples: ['Create a new order', 'Create a new customer', 'Assign a rider to an order', "Repeat yesterday's orders"]
|
||||
},
|
||||
{
|
||||
title: 'Orders & deliveries',
|
||||
description: 'Live counts, trends and status from the order board.',
|
||||
examples: ['How many orders today?', 'Which orders are delayed?', 'Orders today vs yesterday']
|
||||
},
|
||||
{
|
||||
title: 'Riders & fleet',
|
||||
description: 'Who is working, which vehicles are free, and how each hub is doing.',
|
||||
examples: ['How many riders are active?', 'How many vehicles are available?', 'Current hub status']
|
||||
},
|
||||
{
|
||||
title: 'Money & reports',
|
||||
description: 'Revenue, consignments and exceptions that need attention.',
|
||||
examples: ['Total revenue today', 'How many consignments do we have?', 'Show open exceptions']
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Answers a greeting / capability / thanks message, or returns null when the
|
||||
* message is something else (the caller then routes it normally, using
|
||||
* `rest` so the greeting doesn't confuse the router).
|
||||
*
|
||||
* Returns { kind, title, summary, capabilities?, rest }.
|
||||
*/
|
||||
export const answerSmallTalk = (text, { name = '', now = new Date() } = {}) => {
|
||||
const { greeting, rest } = splitGreeting(text, now);
|
||||
const who = String(name || '').trim().split(/\s+/)[0];
|
||||
const hello = greeting ? `${greeting}${who ? `, ${who}` : ''}!` : '';
|
||||
|
||||
const intro =
|
||||
'I’m MileTruth, your Doormile operations assistant. I read live data from the console to answer questions, and I can create orders and customers for you — always showing you exactly what will be saved before anything is sent.';
|
||||
|
||||
if (!rest || isCapabilitiesQuestion(rest)) {
|
||||
return {
|
||||
kind: greeting && !rest ? 'greeting' : 'capabilities',
|
||||
title: hello ? `${hello} Here’s what I can do for you.` : 'Here’s what I can do for you.',
|
||||
summary: `${intro} Click any example below to try it, or just type your question.`,
|
||||
capabilities: CAPABILITIES,
|
||||
rest: ''
|
||||
};
|
||||
}
|
||||
|
||||
if (isThanks(rest)) {
|
||||
return {
|
||||
kind: 'thanks',
|
||||
title: 'You’re welcome! Anything else I can help with?',
|
||||
summary: 'Ask about orders, riders, hubs or revenue — or say “what can you do?” to see everything.',
|
||||
rest: ''
|
||||
};
|
||||
}
|
||||
|
||||
// A greeting in front of a real question: let the question through.
|
||||
return greeting ? { kind: 'passthrough', greeting: hello, rest } : null;
|
||||
};
|
||||
Reference in New Issue
Block a user