From ce6c9ec60afec06c0ec3796d99289ea9588685ae Mon Sep 17 00:00:00 2001 From: NODA1 System Date: Fri, 20 Feb 2026 19:17:18 +0100 Subject: [PATCH] gateway: add natural-language action mapping for reminders and mentor relay --- gateway-bot/http_api.py | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/gateway-bot/http_api.py b/gateway-bot/http_api.py index 2466f166..b6c5eb1a 100644 --- a/gateway-bot/http_api.py +++ b/gateway-bot/http_api.py @@ -521,6 +521,57 @@ async def _handle_action_commands( return None +def _extract_nl_action_command(text: str) -> Optional[str]: + t = (text or "").strip() + if not t or t.startswith("/"): + return None + + low = t.lower() + + # Reminder by relative duration (UA/RU/EN) + m = re.match( + r"^(?:нагадай(?:\s+мені)?|напомни(?:\s+мне)?|remind me)\s+(?:через|in)\s+(\d+)\s*(хв|мин|m|год|hour|h|дн|день|day|d)\s+(.+)$", + low, + ) + if m: + value = m.group(1) + unit = m.group(2) + payload = t[m.end(2):].strip() + if payload: + norm = "m" + if unit in {"год", "hour", "h"}: + norm = "h" + elif unit in {"дн", "день", "day", "d"}: + norm = "d" + return f"/remind_in {value}{norm} {payload}" + + # Reminder by absolute datetime (UA/RU/EN) + m2 = re.match( + r"^(?:нагадай(?:\s+мені)?|напомни(?:\s+мне)?|remind me)\s+(?:на|at)\s+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2})\s+(.+)$", + low, + ) + if m2: + dt = m2.group(1) + payload = t[m2.end(1):].strip() + if payload: + return f"/remind {dt} {payload}" + + # Mentor relay intent + for prefix in ( + "передай менторам ", + "надішли менторам ", + "напиши менторам ", + "send to mentors ", + "relay to mentors ", + ): + if low.startswith(prefix): + payload = t[len(prefix):].strip() + if payload: + return f"/relay_mentors {payload}" + + return None + + def _extract_preferred_language_from_profile_fact(fact: Optional[Dict[str, Any]]) -> Optional[str]: if not isinstance(fact, dict): return None @@ -2696,6 +2747,21 @@ async def handle_telegram_webhook( ) if command_result is not None: return command_result + + nl_command = _extract_nl_action_command(text) + if nl_command: + logger.info(f"{agent_config.name}: NL action mapped to command: {nl_command}") + nl_result = await _handle_action_commands( + agent_config=agent_config, + text=nl_command, + chat_id=chat_id, + user_id=user_id, + username=username, + dao_id=dao_id, + telegram_token=telegram_token, + ) + if nl_result is not None: + return nl_result mentioned_bots = extract_bot_mentions(text) needs_complex_reasoning = requires_complex_reasoning(text)