From ef1e28b73a6daba94ab2e754dc3e5179f14d881d Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 17 May 2026 22:26:51 +0800 Subject: [PATCH] fix(telegram): keep url buttons out of callback assertions --- apps/api/src/services/telegram_gateway.py | 2 +- .../test_telegram_gateway_llm_buttons.py | 24 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index 423d26f7..b96f6797 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -2212,7 +2212,7 @@ class TelegramGateway: return {"inline_keyboard": buttons} - # ── YAML Fallback 路徑(原有邏輯,不改動任何行為)──────────────────── + # ── YAML Fallback 路徑(保留既有 callback 佈局,另補 AwoooP evidence deep link)──── # 2026-04-14 Claude Sonnet 4.6 (Phase 5 Sprint 5.4): # 從 callback_action_spec registry 動態產生按鈕(原 _CATEGORY_BUTTONS hardcode 已下架) # 優點:新增按鈕只需改 yaml,callback_data 格式由 spec.callback_format 決定 diff --git a/apps/api/tests/test_telegram_gateway_llm_buttons.py b/apps/api/tests/test_telegram_gateway_llm_buttons.py index fdf5551c..5f5390a6 100644 --- a/apps/api/tests/test_telegram_gateway_llm_buttons.py +++ b/apps/api/tests/test_telegram_gateway_llm_buttons.py @@ -22,7 +22,6 @@ B3: LLM 動態 Telegram 按鈕 — 單元測試 from __future__ import annotations -import os from dataclasses import dataclass, field from typing import Literal from unittest.mock import AsyncMock, MagicMock, patch @@ -296,6 +295,14 @@ class TestBuildInlineKeyboardRouting: def _first_row_texts(self, keyboard: dict) -> list[str]: return [btn["text"] for btn in keyboard["inline_keyboard"][0]] + def _callback_data_values(self, keyboard: dict, *, start_row: int = 0) -> list[str]: + return [ + btn["callback_data"] + for row in keyboard["inline_keyboard"][start_row:] + for btn in row + if "callback_data" in btn + ] + async def _build_kb(self, gw, **kwargs) -> dict: """await _build_inline_keyboard,mock 掉 Redis。""" mock_redis = MagicMock() @@ -315,7 +322,7 @@ class TestBuildInlineKeyboardRouting: assert "✅ 批准" in first_texts assert "❌ 拒絕" in first_texts # LLM 按鈕不應出現(la: 前綴代表 llm_action) - all_cbs = [btn["callback_data"] for row in kb["inline_keyboard"] for btn in row] + all_cbs = self._callback_data_values(kb) assert not any(cb.startswith("la:") for cb in all_cbs) # Test 2: flag=true + actions 空 → YAML fallback @@ -329,7 +336,7 @@ class TestBuildInlineKeyboardRouting: first_texts = self._first_row_texts(kb) assert "✅ 批准" in first_texts assert "❌ 拒絕" in first_texts - all_cbs = [btn["callback_data"] for row in kb["inline_keyboard"] for btn in row] + all_cbs = self._callback_data_values(kb) assert not any(cb.startswith("la:") for cb in all_cbs) # Test 2b: flag=true + action_plan=None → YAML fallback @@ -357,7 +364,7 @@ class TestBuildInlineKeyboardRouting: assert "❌ 拒絕" in first_texts # LLM 按鈕在第二排以後(P0 Fix 後 16-hex-chars) - all_cbs = [btn["callback_data"] for row in kb["inline_keyboard"][1:] for btn in row] + all_cbs = self._callback_data_values(kb, start_row=1) assert any(re.fullmatch(r"la:[0-9a-f]{16}", cb) for cb in all_cbs), ( f"LLM 按鈕 callback_data 格式應為 la:{{16-hex}},實際: {all_cbs}" ) @@ -376,5 +383,10 @@ class TestBuildInlineKeyboardRouting: first_texts = self._first_row_texts(kb) assert first_texts[0] == "✅ 批准" assert first_texts[1] == "❌ 拒絕" - # 總排數 = 1 (approve/reject) + 2 (3 actions, 2 per row) - assert len(kb["inline_keyboard"]) == 3 + # callback 操作排數 = 1 (approve/reject) + 2 (3 actions, 2 per row); + # AwoooP evidence URL 另加一排,沒有 callback_data。 + callback_rows = [ + row for row in kb["inline_keyboard"] + if any("callback_data" in btn for btn in row) + ] + assert len(callback_rows) == 3