fix(openclaw): route wakeup phrases back to menu
All checks were successful
CD Pipeline / deploy (push) Successful in 2m55s

This commit is contained in:
OoO
2026-05-02 16:03:49 +08:00
parent 673982d83b
commit 7b6423fa67
3 changed files with 87 additions and 1 deletions

2
app.py
View File

@@ -96,7 +96,7 @@ except Exception as e:
# 🚩 系統版本定義 (備份與顯示用)
# 🚩 2026-05-01 V10.76: Move monthly analysis report onto V2 shell
SYSTEM_VERSION = "V10.76"
SYSTEM_VERSION = "V10.77"
# ==========================================
# 🔒 SQL Injection 防護函數

View File

@@ -4166,6 +4166,63 @@ _HELP_KEYWORDS = (
'使用說明', '操作說明', 'help', '幫助',
)
_WAKEUP_KEYWORDS = (
'小o',
'小o小龍蝦',
'小o_小龍蝦',
'小龍蝦',
'openclaw',
)
_BUSINESS_KEYWORDS = (
'業績', '營收', '銷售', '銷量', '熱銷', '商品', '廠商', '目標',
'報表', '趨勢', '分析', '簡報', '比價', '競品', '補貨', '促銷',
'異常', '健康', '分類', '策略', '天氣', '新聞', '匯率', '節慶',
'價格', '今日', '昨日', '今天', '本週', '上週', '本月', '上月', '今年',
)
_GREETING_KEYWORDS = (
'你好', '', '哈囉', '早安', '午安', '晚安', '在嗎', '你有空', '在不在',
'hello', 'hi', 'hey',
)
def _normalize_nl_query(q: str) -> str:
"""V-Fix去除 NL 句尾符號與空白,降低誤判率。"""
return re.sub(r'[\s_\-,:;,.,。!?"“”\(\)\[\]<>]+', '', (q or '').lower())
def _contains_business_signal(q: str) -> bool:
"""V-Fix是否包含可直接進 AI 查詢邏輯的業務關鍵字。"""
ql = (q or '').lower()
return any(kw in ql for kw in _BUSINESS_KEYWORDS)
def _looks_like_wakeup_prompt(q: str) -> bool:
"""V-Fix防止只叫名字/打招呼時走自由生成。"""
ql = (q or '').lower().strip()
if not ql:
return False
compact = _normalize_nl_query(ql)
if not compact:
return False
if compact in _WAKEUP_KEYWORDS:
return True
if (
any(name in compact for name in _WAKEUP_KEYWORDS)
and not _contains_business_signal(ql)
and len(compact) <= 18
):
return True
if compact in _GREETING_KEYWORDS and len(compact) <= 10:
return True
return False
def _is_help_question(q: str) -> bool:
ql = q.lower()
return any(kw in ql for kw in _HELP_KEYWORDS)
@@ -4392,6 +4449,17 @@ def openclaw_answer(question: str, chat_id: int = None):
today_str = now.strftime("%Y/%m/%d")
history_ctx = openclaw_session.history_as_prompt(chat_id) if chat_id else ""
# ── 只叫名 / 問候:先導回主選單,避免題外市場回覆 ───────────────
if _looks_like_wakeup_prompt(question):
wakeup_text = (
"👋 *OpenClaw小O* 在!\n\n"
"你可以直接點下面按鈕,或直接問我:\n"
" 「今天業績如何?」\n"
" 「怎麼查看熱銷商品?」\n"
" 「有什麼市場情報?」"
)
return wakeup_text, quick_menu_keyboard()
# ── 功能說明直接導 help ───────────────────────────────────
if _is_help_question(question):
help_text = (

View File

@@ -38,6 +38,24 @@ def test_webhook_menu_command_handles_bot_suffix(monkeypatch):
assert calls == [("menu", "", -200, 55)]
def test_openclaw_answer_wakeup_query_returns_menu():
from routes import openclaw_bot_routes as bot
text, kb = bot.openclaw_answer("小龍蝦")
assert "OpenClaw小O" in text
assert kb == bot.quick_menu_keyboard()
def test_openclaw_answer_variants_are_menu_wakeup():
from routes import openclaw_bot_routes as bot
assert bot._looks_like_wakeup_prompt("小O_小龍蝦") is True
assert bot._looks_like_wakeup_prompt("Hello, 小O") is True
assert bot._looks_like_wakeup_prompt("今天業績") is False
assert bot._looks_like_wakeup_prompt("你好") is True
def test_private_menu_command_is_allowed_when_no_whitelist_and_fallback_enabled(monkeypatch):
from routes import openclaw_bot_routes as bot