/** * Keyword-based command parser. * * Maps spoken text to robot actions via regex matching. * Supports both French and English keywords, responds in the detected language. * Returns { response, action? } — designed to be a drop-in replacement * for an LLM-based parser in V2 (same parse() interface). */ const COMMANDS = [ { pattern: /\b(wake\s*up|r[eé]veille[- ]?toi|debout)\b/i, response: { fr: "Je me r\u00e9veille !", en: "Waking up!" }, action: { type: "wakeUp" }, }, { pattern: /\b((go\s*to\s*)?sleep|dors|endors[- ]?toi|au dodo)\b/i, response: { fr: "Je vais dormir.", en: "Going to sleep." }, action: { type: "gotoSleep" }, }, { pattern: /\b(look\s+left|regarde\s+[àa]\s+gauche|tourne\s+[àa]\s+gauche|gauche)\b/i, response: { fr: "Je regarde \u00e0 gauche.", en: "Looking left." }, action: { type: "lookDirection", params: { direction: "left" } }, }, { pattern: /\b(look\s+right|regarde\s+[àa]\s+droite|tourne\s+[àa]\s+droite|droite)\b/i, response: { fr: "Je regarde \u00e0 droite.", en: "Looking right." }, action: { type: "lookDirection", params: { direction: "right" } }, }, { pattern: /\b(look\s+up|regarde\s+en\s+haut|l[eè]ve\s+la\s+t[eê]te|en haut)\b/i, response: { fr: "Je regarde en haut.", en: "Looking up." }, action: { type: "lookDirection", params: { direction: "up" } }, }, { pattern: /\b(look\s+down|regarde\s+en\s+bas|baisse\s+la\s+t[eê]te|en bas)\b/i, response: { fr: "Je regarde en bas.", en: "Looking down." }, action: { type: "lookDirection", params: { direction: "down" } }, }, { pattern: /\b(look\s+(at\s+me|center|straight|forward)|centre|regarde[- ]?moi|devant\s+toi|en face)\b/i, response: { fr: "Me voil\u00e0 !", en: "Here I am!" }, action: { type: "lookDirection", params: { direction: "center" } }, }, { pattern: /\b(turn\s+around|tourne[- ]?toi|fais\s+un\s+tour|retourne[- ]?toi|demi[- ]?tour)\b/i, response: { fr: "Youhou !", en: "Wheee!" }, action: { type: "turnAround" }, }, { pattern: /\b(hello|hi|hey|bonjour|salut|coucou)\b/i, response: { fr: "Bonjour ! Ravi de te parler.", en: "Hello! Nice to talk to you." }, action: { type: "wiggleAntennas" }, }, { pattern: /\b(help|what can you do|commands|aide|qu'?est[- ]ce que tu (sais|peux) faire|que sais[- ]tu faire)\b/i, response: { fr: "Je peux : me r\u00e9veiller, dormir, regarder \u00e0 gauche/droite/haut/bas, te regarder, me retourner, et dire bonjour !", en: "I can: wake up, go to sleep, look left/right/up/down, look at me, turn around, and say hello!", }, action: { type: "nod" }, }, ]; /** * Pick the response string for the detected language, falling back to French. */ function localize(response, lang) { if (typeof response === "string") return response; return response[lang] || response.fr; } /** * Parse spoken text into a response and optional robot action. * @param {string} text * @param {string} language Detected language code, e.g. "fr", "en" * @returns {{ response: string, action?: { type: string, params?: object } }} */ export function parse(text, language = "fr") { const trimmed = text.trim(); if (!trimmed) { return { response: localize({ fr: "Je n'ai pas compris.", en: "I didn't catch that." }, language) }; } for (const cmd of COMMANDS) { if (cmd.pattern.test(trimmed)) { return { response: localize(cmd.response, language), action: cmd.action, }; } } // Fallback — echo what we heard with a quizzical reaction const fallback = language === "en" ? `I heard: "${trimmed}"` : `J'ai entendu : \u00ab ${trimmed} \u00bb`; return { response: fallback, action: { type: "headTilt" }, }; }