smart-bot-factory 0.2.4__py3-none-any.whl → 0.2.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of smart-bot-factory might be problematic. Click here for more details.

@@ -52,8 +52,12 @@ class BotBuilder:
52
52
  self._message_validators: List = [] # Валидация ДО обработки
53
53
  self._prompt_enrichers: List = [] # Обогащение системного промпта
54
54
  self._context_enrichers: List = [] # Обогащение контекста для AI
55
+ self._response_processors: List = [] # Обработка ответа AI
55
56
  self._send_filters: List = [] # Фильтры перед отправкой пользователю
56
57
 
58
+ # Кастомный PromptLoader
59
+ self._custom_prompt_loader = None
60
+
57
61
  # Флаги инициализации
58
62
  self._initialized = False
59
63
 
@@ -174,10 +178,16 @@ class BotBuilder:
174
178
  else:
175
179
  logger.info(f"✅ Router Manager уже был создан ранее")
176
180
 
177
- # Prompt Loader
178
- self.prompt_loader = PromptLoader(
179
- prompts_dir=self.config.PROMT_FILES_DIR
180
- )
181
+ # Prompt Loader (используем кастомный если установлен)
182
+ if self._custom_prompt_loader:
183
+ self.prompt_loader = self._custom_prompt_loader
184
+ logger.info(f"✅ Используется кастомный Prompt Loader: {type(self.prompt_loader).__name__}")
185
+ else:
186
+ self.prompt_loader = PromptLoader(
187
+ prompts_dir=self.config.PROMT_FILES_DIR
188
+ )
189
+ logger.info(f"✅ Используется стандартный Prompt Loader")
190
+
181
191
  await self.prompt_loader.validate_prompts()
182
192
  logger.info(f"✅ Prompt Loader инициализирован")
183
193
 
@@ -364,6 +374,34 @@ class BotBuilder:
364
374
  """Получает список обработчиков on_start"""
365
375
  return self._start_handlers.copy()
366
376
 
377
+ def set_prompt_loader(self, prompt_loader):
378
+ """
379
+ Устанавливает кастомный PromptLoader
380
+
381
+ Должен быть вызван ДО build()
382
+
383
+ Args:
384
+ prompt_loader: Экземпляр PromptLoader или его наследника (например UserPromptLoader)
385
+
386
+ Example:
387
+ from smart_bot_factory.utils import UserPromptLoader
388
+
389
+ # Использовать UserPromptLoader с автопоиском prompts_dir
390
+ custom_loader = UserPromptLoader("my-bot")
391
+ bot_builder.set_prompt_loader(custom_loader)
392
+
393
+ # Или кастомный наследник
394
+ class MyPromptLoader(UserPromptLoader):
395
+ def __init__(self, bot_id):
396
+ super().__init__(bot_id)
397
+ self.extra_file = self.prompts_dir / 'extra.txt'
398
+
399
+ my_loader = MyPromptLoader("my-bot")
400
+ bot_builder.set_prompt_loader(my_loader)
401
+ """
402
+ self._custom_prompt_loader = prompt_loader
403
+ logger.info(f"✅ Установлен кастомный PromptLoader: {type(prompt_loader).__name__}")
404
+
367
405
  # ========== ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ ==========
368
406
 
369
407
  def validate_message(self, handler):
@@ -437,6 +475,28 @@ class BotBuilder:
437
475
  logger.info(f"✅ Зарегистрирован обогатитель контекста: {handler.__name__}")
438
476
  return handler
439
477
 
478
+ def process_response(self, handler):
479
+ """
480
+ Регистрирует обработчик ответа AI (ПОСЛЕ получения ответа)
481
+
482
+ Args:
483
+ handler: async def(response_text: str, ai_metadata: dict, user_id: int) -> tuple[str, dict]
484
+
485
+ Example:
486
+ @bot_builder.process_response
487
+ async def modify_response(response_text, ai_metadata, user_id):
488
+ # Модифицируем ответ
489
+ if "цена" in response_text.lower():
490
+ response_text += "\\n\\n💰 Актуальные цены на сайте"
491
+ return response_text, ai_metadata
492
+ """
493
+ if not callable(handler):
494
+ raise TypeError(f"Обработчик должен быть callable, получен {type(handler)}")
495
+
496
+ self._response_processors.append(handler)
497
+ logger.info(f"✅ Зарегистрирован обработчик ответа: {handler.__name__}")
498
+ return handler
499
+
440
500
  def filter_send(self, handler):
441
501
  """
442
502
  Регистрирует фильтр отправки (может блокировать отправку пользователю)
@@ -466,6 +526,7 @@ class BotBuilder:
466
526
  'validators': self._message_validators.copy(),
467
527
  'prompt_enrichers': self._prompt_enrichers.copy(),
468
528
  'context_enrichers': self._context_enrichers.copy(),
529
+ 'response_processors': self._response_processors.copy(),
469
530
  'send_filters': self._send_filters.copy()
470
531
  }
471
532
 
@@ -624,6 +624,19 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
624
624
 
625
625
  logger.info(f"✅ Финальный текст для отправки: {len(response_text)} символов")
626
626
 
627
+ # ============ ХУК 4: ОБРАБОТКА ОТВЕТА ============
628
+ response_processors = message_hooks.get('response_processors', [])
629
+ for processor in response_processors:
630
+ try:
631
+ response_text, ai_metadata = await processor(
632
+ response_text,
633
+ ai_metadata,
634
+ message.from_user.id
635
+ )
636
+ logger.info(f"✅ Ответ обработан '{processor.__name__}'")
637
+ except Exception as e:
638
+ logger.error(f"❌ Ошибка в обработчике ответа '{processor.__name__}': {e}")
639
+
627
640
  # Обновляем этап сессии и качество лида
628
641
  if ai_metadata:
629
642
  logger.info("🔍 Анализ метаданных от ИИ:")
@@ -732,7 +745,7 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
732
745
 
733
746
  logger.info(f"📱 Отправляем пользователю: {len(final_response)} символов")
734
747
 
735
- # ============ ХУК 4: ФИЛЬТРЫ ОТПРАВКИ ============
748
+ # ============ ХУК 5: ФИЛЬТРЫ ОТПРАВКИ ============
736
749
  send_filters = message_hooks.get('send_filters', [])
737
750
  for filter_func in send_filters:
738
751
  try:
@@ -32,10 +32,10 @@ class SupabaseClient:
32
32
  # Автоматически загружаем настройки из .env
33
33
  self._load_env_config()
34
34
 
35
- # Инициализируем клиент
36
- self.client: Optional[Client] = None
35
+ # Инициализируем клиент СИНХРОННО прямо в __init__
36
+ self.client = create_client(self.url, self.key)
37
37
 
38
- logger.info(f"🚀 Инициализация SupabaseClient для bot_id: {self.bot_id}")
38
+ logger.info(f" SupabaseClient инициализирован для bot_id: {self.bot_id}")
39
39
 
40
40
  def _load_env_config(self):
41
41
  """Загружает конфигурацию из .env файла"""
@@ -80,15 +80,6 @@ class SupabaseClient:
80
80
  logger.error(f" Искали в: {bot_env_path}")
81
81
  return None
82
82
 
83
- async def initialize(self):
84
- """Инициализация клиента Supabase"""
85
- try:
86
- self.client = create_client(self.url, self.key)
87
- logger.info(f"✅ Supabase client инициализирован{f' для bot_id: {self.bot_id}' if self.bot_id else ''}")
88
- except Exception as e:
89
- logger.error(f"❌ Ошибка инициализации Supabase client: {e}")
90
- raise
91
-
92
83
  # =============================================================================
93
84
  # МЕТОДЫ ДЛЯ РАБОТЫ С ПОЛЬЗОВАТЕЛЯМИ
94
85
  # =============================================================================
@@ -2,8 +2,9 @@
2
2
  Utils модули smart_bot_factory
3
3
  """
4
4
 
5
- from ..integrations.supabase_client import SupabaseClient
6
- from ..utils.prompt_loader import PromptLoader
7
- from ..utils.debug_routing import setup_debug_handlers
8
5
 
9
- __all__ = ['SupabaseClient', 'PromptLoader', 'setup_debug_handlers']
6
+ from .user_prompt_loader import UserPromptLoader
7
+
8
+ __all__ = [ # Базовый класс (для библиотеки)
9
+ 'UserPromptLoader', # Для пользователей (автопоиск prompts_dir)
10
+ ]
@@ -0,0 +1,56 @@
1
+ """
2
+ UserPromptLoader - упрощенный PromptLoader для пользователей библиотеки
3
+ с автоматическим поиском prompts_dir от корня проекта
4
+ """
5
+
6
+ import logging
7
+ from pathlib import Path
8
+ from .prompt_loader import PromptLoader
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class UserPromptLoader(PromptLoader):
14
+ """
15
+ PromptLoader для пользователей библиотеки с автоматическим поиском prompts_dir
16
+
17
+ Автоматически находит папку prompts для указанного бота от корня проекта
18
+ Наследуется от базового PromptLoader - все методы доступны
19
+ """
20
+
21
+ def __init__(self, bot_id: str, prompts_subdir: str = "prompts"):
22
+ """
23
+ Инициализация загрузчика промптов с автоматическим поиском
24
+
25
+ Args:
26
+ bot_id: Идентификатор бота
27
+ prompts_subdir: Подпапка с промптами (по умолчанию "prompts")
28
+
29
+ Example:
30
+ # Автоматически найдет bots/my-bot/prompts
31
+ loader = UserPromptLoader("my-bot")
32
+
33
+ # Или кастомную подпапку
34
+ loader = UserPromptLoader("my-bot", "custom_prompts")
35
+
36
+ # Наследование для кастомизации
37
+ class MyLoader(UserPromptLoader):
38
+ def __init__(self, bot_id):
39
+ super().__init__(bot_id)
40
+ # Добавить свою логику
41
+ self.extra_file = self.prompts_dir / 'extra.txt'
42
+ """
43
+ from project_root_finder import root
44
+
45
+ # Автоматически определяем путь к промптам
46
+ prompts_dir = root / "bots" / bot_id / prompts_subdir
47
+
48
+ if not prompts_dir.exists():
49
+ logger.warning(f"⚠️ Папка промптов не найдена: {prompts_dir}")
50
+ logger.warning(f" Создайте папку или проверьте bot_id")
51
+
52
+ # Вызываем базовую инициализацию
53
+ super().__init__(str(prompts_dir))
54
+
55
+ logger.info(f"✅ UserPromptLoader создан для bot_id '{bot_id}': {prompts_dir}")
56
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart-bot-factory
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Библиотека для создания умных чат-ботов
5
5
  Author-email: Kopatych <kopatych@example.com>
6
6
  License: MIT
@@ -33,23 +33,24 @@ smart_bot_factory/core/router_manager.py,sha256=dUwesog-oHk1U2EDdS8p0e4MTSkwtx5_
33
33
  smart_bot_factory/core/states.py,sha256=AOc19_yAsDW_8md-2oiowjBhuW3bwcsmMxszCXWZZTQ,355
34
34
  smart_bot_factory/core/telegram_router.py,sha256=LcPLOd87Y4Y4YN6TBXVAtmpSp8gAK2otgMI4YS5f5tk,2091
35
35
  smart_bot_factory/creation/__init__.py,sha256=IgDk8GDS3pg7Pw_Et41J33ZmeZIU5dRwQdTmYKXfJfE,128
36
- smart_bot_factory/creation/bot_builder.py,sha256=vMvjq6deCD_TjkQfAyTlFF1FNXxzA-W0SloLObPK4_M,32620
36
+ smart_bot_factory/creation/bot_builder.py,sha256=Fud-E3J-S7IEjWBfFhRu4YXnJZHbNHG33zqgGk_Cy8I,35585
37
37
  smart_bot_factory/creation/bot_testing.py,sha256=JDWXyJfZmbgo-DLdAPk8Sd9FiehtHHa4sLD17lBrTOc,55669
38
38
  smart_bot_factory/event/__init__.py,sha256=hPL449RULIOB-OXv1ZbGNiHctAYaOMUqhSWGPrDHYBM,212
39
- smart_bot_factory/handlers/handlers.py,sha256=BZ9KSFnudVg3iU_XuNI0hter7ZOl9Kc6P4TyLwPh0AM,40803
39
+ smart_bot_factory/handlers/handlers.py,sha256=jtCf8XiJD3pIjcd7vqT8uG8Q-qiHd1W-ZLZiVPK8YR4,41458
40
40
  smart_bot_factory/integrations/openai_client.py,sha256=aMcDrKO0GEx3ZSVEOGDeDtFCDWSXs6biUfgrbRK8yTU,23180
41
41
  smart_bot_factory/integrations/supabase_client.py,sha256=AfALLZdDYeMWHLJw6POTGiBd-sH3i03oT6tT7m9C28I,44644
42
42
  smart_bot_factory/message/__init__.py,sha256=8XWEEl3J0l1xDeEPmXPwFbHbnQelGApCwnicUkcBbOg,391
43
43
  smart_bot_factory/router/__init__.py,sha256=QrfO5u8H2uVzWGMtBvNKunsJAv7UrKtvt2f_D5xSFWE,270
44
44
  smart_bot_factory/supabase/__init__.py,sha256=XmZP6yM9ffERM5ddAWyJnrNzEhCYtMu3AcjVCi1rOf8,179
45
- smart_bot_factory/supabase/client.py,sha256=8_-I3kxZQlKQElI4cTUjNGYcqlyIyEkSrUZaP0nfNNU,26044
45
+ smart_bot_factory/supabase/client.py,sha256=lWIzfOgoSvU7xPhYLoJtM5GnbWdoWsvHcRFC22sFBMU,25637
46
46
  smart_bot_factory/table/database_structure.sql,sha256=26gFtMC2jdQGQF7Zb_F4Br56rMd4hUDTk9FkNZYneLo,2789
47
47
  smart_bot_factory/table/schema.sql,sha256=-6kOmA9QnSkUtmGI2iQRbTvbdiqOhEOQcuz1lJn79mU,28059
48
- smart_bot_factory/utils/__init__.py,sha256=5zNjw491bj5VkOhoEAwh2hjmv8nldyDOTrG7pbGpz6A,285
48
+ smart_bot_factory/utils/__init__.py,sha256=UhsJXEHfrIK8h1AHsroHSwAriijk-LvnqLyvgzi2VYs,273
49
49
  smart_bot_factory/utils/debug_routing.py,sha256=BOoDhKBg7UXe5uHQxRk3TSfPfLPOFqt0N7lAo6kjCOo,4719
50
50
  smart_bot_factory/utils/prompt_loader.py,sha256=JSn7CsWnToSbHYtURdeuZn7ectyDqQGrPGHN2ixIGkw,19930
51
- smart_bot_factory-0.2.4.dist-info/METADATA,sha256=_P5444XCJBJNPtAd8lTOHUhAgWAfKQ2P_tlQsuuMn7I,28224
52
- smart_bot_factory-0.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
- smart_bot_factory-0.2.4.dist-info/entry_points.txt,sha256=ybKEAI0WSb7WoRiey7QE-HHfn88UGV7nxLDxXq7b7SU,50
54
- smart_bot_factory-0.2.4.dist-info/licenses/LICENSE,sha256=OrK3cwdUTzNzIhJvSPtJaVMoYIyC_sSx5EFE_FDMvGs,1092
55
- smart_bot_factory-0.2.4.dist-info/RECORD,,
51
+ smart_bot_factory/utils/user_prompt_loader.py,sha256=dk6P0X_3UcNqxjRtuIvb0LcPrp03zIIsstZwdmeCPaE,2519
52
+ smart_bot_factory-0.2.6.dist-info/METADATA,sha256=HFUAtOVAOW7_sf2S5Bsqx6WQVTRsb4NSkMy_vqQeUQ0,28224
53
+ smart_bot_factory-0.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
54
+ smart_bot_factory-0.2.6.dist-info/entry_points.txt,sha256=ybKEAI0WSb7WoRiey7QE-HHfn88UGV7nxLDxXq7b7SU,50
55
+ smart_bot_factory-0.2.6.dist-info/licenses/LICENSE,sha256=OrK3cwdUTzNzIhJvSPtJaVMoYIyC_sSx5EFE_FDMvGs,1092
56
+ smart_bot_factory-0.2.6.dist-info/RECORD,,