smart-bot-factory 0.2.2__py3-none-any.whl → 0.2.4__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.
- smart_bot_factory/core/message_sender.py +241 -0
- smart_bot_factory/creation/bot_builder.py +0 -24
- smart_bot_factory/handlers/handlers.py +3 -20
- smart_bot_factory/message/__init__.py +2 -0
- {smart_bot_factory-0.2.2.dist-info → smart_bot_factory-0.2.4.dist-info}/METADATA +1 -1
- {smart_bot_factory-0.2.2.dist-info → smart_bot_factory-0.2.4.dist-info}/RECORD +11 -11
- /smart_bot_factory/{database → table}/database_structure.sql +0 -0
- /smart_bot_factory/{database → table}/schema.sql +0 -0
- {smart_bot_factory-0.2.2.dist-info → smart_bot_factory-0.2.4.dist-info}/WHEEL +0 -0
- {smart_bot_factory-0.2.2.dist-info → smart_bot_factory-0.2.4.dist-info}/entry_points.txt +0 -0
- {smart_bot_factory-0.2.2.dist-info → smart_bot_factory-0.2.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -449,3 +449,244 @@ async def get_users_by_stage_stats(
|
|
|
449
449
|
"error": str(e),
|
|
450
450
|
"bot_id": bot_id
|
|
451
451
|
}
|
|
452
|
+
|
|
453
|
+
async def send_message(
|
|
454
|
+
message,
|
|
455
|
+
text: str,
|
|
456
|
+
supabase_client,
|
|
457
|
+
files_list: list = [],
|
|
458
|
+
directories_list: list = [],
|
|
459
|
+
parse_mode: str = "Markdown",
|
|
460
|
+
**kwargs
|
|
461
|
+
):
|
|
462
|
+
"""
|
|
463
|
+
Пользовательская функция для отправки сообщений с файлами и кнопками
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
message: Message объект от aiogram
|
|
467
|
+
text: Текст сообщения
|
|
468
|
+
supabase_client: SupabaseClient для работы с БД
|
|
469
|
+
files_list: Список файлов для отправки
|
|
470
|
+
directories_list: Список каталогов (отправятся все файлы)
|
|
471
|
+
parse_mode: Режим парсинга ('Markdown', 'HTML' или None)
|
|
472
|
+
**kwargs: Дополнительные параметры (reply_markup и т.д.)
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
Message объект отправленного сообщения или None
|
|
476
|
+
|
|
477
|
+
Example:
|
|
478
|
+
from smart_bot_factory.message import send_message
|
|
479
|
+
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
|
480
|
+
|
|
481
|
+
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
482
|
+
[InlineKeyboardButton(text="Кнопка", callback_data="action")]
|
|
483
|
+
])
|
|
484
|
+
|
|
485
|
+
await send_message(
|
|
486
|
+
message=message,
|
|
487
|
+
text="Привет!",
|
|
488
|
+
supabase_client=supabase_client,
|
|
489
|
+
files_list=["file.pdf"],
|
|
490
|
+
parse_mode="Markdown",
|
|
491
|
+
reply_markup=keyboard
|
|
492
|
+
)
|
|
493
|
+
"""
|
|
494
|
+
from pathlib import Path
|
|
495
|
+
from aiogram.types import FSInputFile
|
|
496
|
+
from aiogram.utils.media_group import MediaGroupBuilder
|
|
497
|
+
|
|
498
|
+
logger.info(f"📤 send_message вызвана:")
|
|
499
|
+
logger.info(f" 👤 Пользователь: {message.from_user.id}")
|
|
500
|
+
logger.info(f" 📝 Длина текста: {len(text)} символов")
|
|
501
|
+
logger.info(f" 🔧 Parse mode: {parse_mode}")
|
|
502
|
+
|
|
503
|
+
try:
|
|
504
|
+
user_id = message.from_user.id
|
|
505
|
+
|
|
506
|
+
# Устанавливаем parse_mode (None если передана строка 'None')
|
|
507
|
+
actual_parse_mode = None if parse_mode == 'None' else parse_mode
|
|
508
|
+
|
|
509
|
+
# Текст уже готов, используем как есть
|
|
510
|
+
final_text = text
|
|
511
|
+
|
|
512
|
+
# Работаем с переданными файлами и каталогами
|
|
513
|
+
logger.info(f" 📦 Передано файлов: {files_list}")
|
|
514
|
+
logger.info(f" 📂 Передано каталогов: {directories_list}")
|
|
515
|
+
|
|
516
|
+
# Получаем список уже отправленных файлов и каталогов
|
|
517
|
+
sent_files = await supabase_client.get_sent_files(user_id)
|
|
518
|
+
sent_directories = await supabase_client.get_sent_directories(user_id)
|
|
519
|
+
|
|
520
|
+
logger.info(f" 📋 Уже отправлено файлов: {sent_files}")
|
|
521
|
+
logger.info(f" 📋 Уже отправлено каталогов: {sent_directories}")
|
|
522
|
+
|
|
523
|
+
# Фильтруем файлы и каталоги, которые уже отправлялись
|
|
524
|
+
actual_files_list = [f for f in files_list if f not in sent_files]
|
|
525
|
+
actual_directories_list = [d for d in directories_list if str(d) not in sent_directories]
|
|
526
|
+
|
|
527
|
+
logger.info(f" 🆕 После фильтрации файлов: {actual_files_list}")
|
|
528
|
+
logger.info(f" 🆕 После фильтрации каталогов: {actual_directories_list}")
|
|
529
|
+
|
|
530
|
+
# Проверяем, что есть что отправлять
|
|
531
|
+
if not final_text or not final_text.strip():
|
|
532
|
+
logger.error(f"❌ КРИТИЧЕСКАЯ ОШИБКА: final_text пуст после обработки!")
|
|
533
|
+
logger.error(f" Исходный text: '{text[:200]}...'")
|
|
534
|
+
final_text = "Ошибка формирования ответа. Попробуйте еще раз."
|
|
535
|
+
|
|
536
|
+
logger.info(f"📱 Подготовка сообщения: {len(final_text)} символов")
|
|
537
|
+
logger.info(f" 📦 Файлов для обработки: {actual_files_list}")
|
|
538
|
+
logger.info(f" 📂 Каталогов для обработки: {actual_directories_list}")
|
|
539
|
+
|
|
540
|
+
# Проверяем наличие файлов для отправки
|
|
541
|
+
if actual_files_list or actual_directories_list:
|
|
542
|
+
# Функция определения типа медиа по расширению
|
|
543
|
+
def get_media_type(file_path: str) -> str:
|
|
544
|
+
ext = Path(file_path).suffix.lower()
|
|
545
|
+
if ext in {'.jpg', '.jpeg', '.png'}:
|
|
546
|
+
return 'photo'
|
|
547
|
+
elif ext in {'.mp4', '.mov'}:
|
|
548
|
+
return 'video'
|
|
549
|
+
else:
|
|
550
|
+
return 'document'
|
|
551
|
+
|
|
552
|
+
# Создаем списки для разных типов файлов
|
|
553
|
+
video_files = []
|
|
554
|
+
photo_files = []
|
|
555
|
+
document_files = []
|
|
556
|
+
|
|
557
|
+
# Функция обработки файла
|
|
558
|
+
def process_file(file_path: Path, source: str = ""):
|
|
559
|
+
if file_path.is_file():
|
|
560
|
+
media_type = get_media_type(str(file_path))
|
|
561
|
+
if media_type == 'video':
|
|
562
|
+
video_files.append(file_path)
|
|
563
|
+
logger.info(f" 🎥 Добавлено видео{f' из {source}' if source else ''}: {file_path.name}")
|
|
564
|
+
elif media_type == 'photo':
|
|
565
|
+
photo_files.append(file_path)
|
|
566
|
+
logger.info(f" 📸 Добавлено фото{f' из {source}' if source else ''}: {file_path.name}")
|
|
567
|
+
else:
|
|
568
|
+
document_files.append(file_path)
|
|
569
|
+
logger.info(f" 📄 Добавлен документ{f' из {source}' if source else ''}: {file_path.name}")
|
|
570
|
+
else:
|
|
571
|
+
logger.warning(f" ⚠️ Файл не найден: {file_path}")
|
|
572
|
+
|
|
573
|
+
# Обрабатываем прямые файлы
|
|
574
|
+
for file_name in actual_files_list:
|
|
575
|
+
try:
|
|
576
|
+
process_file(Path(f"files/{file_name}"))
|
|
577
|
+
except Exception as e:
|
|
578
|
+
logger.error(f" ❌ Ошибка обработки файла {file_name}: {e}")
|
|
579
|
+
|
|
580
|
+
# Обрабатываем файлы из каталогов
|
|
581
|
+
for dir_name in actual_directories_list:
|
|
582
|
+
dir_name = Path(dir_name)
|
|
583
|
+
try:
|
|
584
|
+
if dir_name.is_dir():
|
|
585
|
+
for file_path in dir_name.iterdir():
|
|
586
|
+
try:
|
|
587
|
+
process_file(file_path, dir_name)
|
|
588
|
+
except Exception as e:
|
|
589
|
+
logger.error(f" ❌ Ошибка обработки файла {file_path}: {e}")
|
|
590
|
+
else:
|
|
591
|
+
logger.warning(f" ⚠️ Каталог не найден: {dir_name}")
|
|
592
|
+
except Exception as e:
|
|
593
|
+
logger.error(f" ❌ Ошибка обработки каталога {dir_name}: {e}")
|
|
594
|
+
|
|
595
|
+
# Списки для отслеживания реально отправленных файлов
|
|
596
|
+
sent_files_to_save = []
|
|
597
|
+
sent_dirs_to_save = []
|
|
598
|
+
|
|
599
|
+
# 1. Отправляем видео (если есть)
|
|
600
|
+
if video_files:
|
|
601
|
+
video_group = MediaGroupBuilder()
|
|
602
|
+
for file_path in video_files:
|
|
603
|
+
video_group.add_video(media=FSInputFile(str(file_path)))
|
|
604
|
+
|
|
605
|
+
videos = video_group.build()
|
|
606
|
+
if videos:
|
|
607
|
+
await message.answer_media_group(media=videos)
|
|
608
|
+
logger.info(f" ✅ Отправлено {len(videos)} видео")
|
|
609
|
+
|
|
610
|
+
# 2. Отправляем фото (если есть)
|
|
611
|
+
if photo_files:
|
|
612
|
+
photo_group = MediaGroupBuilder()
|
|
613
|
+
for file_path in photo_files:
|
|
614
|
+
photo_group.add_photo(media=FSInputFile(str(file_path)))
|
|
615
|
+
|
|
616
|
+
photos = photo_group.build()
|
|
617
|
+
if photos:
|
|
618
|
+
await message.answer_media_group(media=photos)
|
|
619
|
+
logger.info(f" ✅ Отправлено {len(photos)} фото")
|
|
620
|
+
|
|
621
|
+
# 3. Отправляем текст
|
|
622
|
+
result = await message.answer(final_text, parse_mode=actual_parse_mode, **kwargs)
|
|
623
|
+
logger.info(f" ✅ Отправлен текст сообщения")
|
|
624
|
+
|
|
625
|
+
# 4. Отправляем документы (если есть)
|
|
626
|
+
if document_files:
|
|
627
|
+
doc_group = MediaGroupBuilder()
|
|
628
|
+
for file_path in document_files:
|
|
629
|
+
doc_group.add_document(media=FSInputFile(str(file_path)))
|
|
630
|
+
|
|
631
|
+
docs = doc_group.build()
|
|
632
|
+
if docs:
|
|
633
|
+
await message.answer_media_group(media=docs)
|
|
634
|
+
logger.info(f" ✅ Отправлено {len(docs)} документов")
|
|
635
|
+
|
|
636
|
+
# 5. Собираем список реально отправленных файлов и каталогов
|
|
637
|
+
if video_files or photo_files or document_files:
|
|
638
|
+
sent_files_to_save.extend(actual_files_list)
|
|
639
|
+
logger.info(f" 📝 Добавляем в список для сохранения файлы: {actual_files_list}")
|
|
640
|
+
sent_dirs_to_save.extend([str(d) for d in actual_directories_list])
|
|
641
|
+
logger.info(f" 📝 Добавляем в список для сохранения каталоги: {actual_directories_list}")
|
|
642
|
+
|
|
643
|
+
# 6. Обновляем информацию в БД
|
|
644
|
+
if sent_files_to_save or sent_dirs_to_save:
|
|
645
|
+
try:
|
|
646
|
+
if sent_files_to_save:
|
|
647
|
+
logger.info(f" 💾 Сохраняем файлы в БД: {sent_files_to_save}")
|
|
648
|
+
await supabase_client.add_sent_files(user_id, sent_files_to_save)
|
|
649
|
+
if sent_dirs_to_save:
|
|
650
|
+
logger.info(f" 💾 Сохраняем каталоги в БД: {sent_dirs_to_save}")
|
|
651
|
+
await supabase_client.add_sent_directories(user_id, sent_dirs_to_save)
|
|
652
|
+
logger.info(f" ✅ Обновлена информация о отправленных файлах в БД")
|
|
653
|
+
except Exception as e:
|
|
654
|
+
logger.error(f" ❌ Ошибка обновления информации о файлах в БД: {e}")
|
|
655
|
+
else:
|
|
656
|
+
logger.info(f" ℹ️ Нет новых файлов для сохранения в БД")
|
|
657
|
+
|
|
658
|
+
return result
|
|
659
|
+
else:
|
|
660
|
+
# Если нет файлов, отправляем просто текст
|
|
661
|
+
logger.info(" ⚠️ Нет файлов для отправки, отправляем как текст")
|
|
662
|
+
result = await message.answer(final_text, parse_mode=actual_parse_mode, **kwargs)
|
|
663
|
+
return result
|
|
664
|
+
|
|
665
|
+
except Exception as e:
|
|
666
|
+
# Проверяем, является ли ошибка блокировкой бота
|
|
667
|
+
if "Forbidden: bot was blocked by the user" in str(e):
|
|
668
|
+
logger.warning(f"🚫 Бот заблокирован пользователем {user_id}")
|
|
669
|
+
return None
|
|
670
|
+
elif "TelegramForbiddenError" in str(type(e).__name__):
|
|
671
|
+
logger.warning(f"🚫 Бот заблокирован пользователем {user_id}")
|
|
672
|
+
return None
|
|
673
|
+
|
|
674
|
+
logger.error(f"❌ ОШИБКА в send_message: {e}")
|
|
675
|
+
logger.exception("Полный стек ошибки send_message:")
|
|
676
|
+
|
|
677
|
+
# Пытаемся отправить простое сообщение без форматирования
|
|
678
|
+
try:
|
|
679
|
+
fallback_text = "Произошла ошибка при отправке ответа. Попробуйте еще раз."
|
|
680
|
+
result = await message.answer(fallback_text)
|
|
681
|
+
logger.info(f"✅ Запасное сообщение отправлено")
|
|
682
|
+
return result
|
|
683
|
+
except Exception as e2:
|
|
684
|
+
if "Forbidden: bot was blocked by the user" in str(e2):
|
|
685
|
+
logger.warning(f"🚫 Бот заблокирован пользователем {user_id} (fallback)")
|
|
686
|
+
return None
|
|
687
|
+
elif "TelegramForbiddenError" in str(type(e2).__name__):
|
|
688
|
+
logger.warning(f"🚫 Бот заблокирован пользователем {user_id} (fallback)")
|
|
689
|
+
return None
|
|
690
|
+
|
|
691
|
+
logger.error(f"❌ Даже запасное сообщение не отправилось: {e2}")
|
|
692
|
+
raise
|
|
@@ -52,7 +52,6 @@ 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
|
|
56
55
|
self._send_filters: List = [] # Фильтры перед отправкой пользователю
|
|
57
56
|
|
|
58
57
|
# Флаги инициализации
|
|
@@ -438,28 +437,6 @@ class BotBuilder:
|
|
|
438
437
|
logger.info(f"✅ Зарегистрирован обогатитель контекста: {handler.__name__}")
|
|
439
438
|
return handler
|
|
440
439
|
|
|
441
|
-
def process_response(self, handler):
|
|
442
|
-
"""
|
|
443
|
-
Регистрирует обработчик ответа AI (ПОСЛЕ получения ответа)
|
|
444
|
-
|
|
445
|
-
Args:
|
|
446
|
-
handler: async def(response_text: str, ai_metadata: dict, user_id: int) -> tuple[str, dict]
|
|
447
|
-
|
|
448
|
-
Example:
|
|
449
|
-
@bot_builder.process_response
|
|
450
|
-
async def modify_response(response_text, ai_metadata, user_id):
|
|
451
|
-
# Модифицируем ответ
|
|
452
|
-
if "цена" in response_text.lower():
|
|
453
|
-
response_text += "\\n\\n💰 Актуальные цены на сайте"
|
|
454
|
-
return response_text, ai_metadata
|
|
455
|
-
"""
|
|
456
|
-
if not callable(handler):
|
|
457
|
-
raise TypeError(f"Обработчик должен быть callable, получен {type(handler)}")
|
|
458
|
-
|
|
459
|
-
self._response_processors.append(handler)
|
|
460
|
-
logger.info(f"✅ Зарегистрирован обработчик ответа: {handler.__name__}")
|
|
461
|
-
return handler
|
|
462
|
-
|
|
463
440
|
def filter_send(self, handler):
|
|
464
441
|
"""
|
|
465
442
|
Регистрирует фильтр отправки (может блокировать отправку пользователю)
|
|
@@ -489,7 +466,6 @@ class BotBuilder:
|
|
|
489
466
|
'validators': self._message_validators.copy(),
|
|
490
467
|
'prompt_enrichers': self._prompt_enrichers.copy(),
|
|
491
468
|
'context_enrichers': self._context_enrichers.copy(),
|
|
492
|
-
'response_processors': self._response_processors.copy(),
|
|
493
469
|
'send_filters': self._send_filters.copy()
|
|
494
470
|
}
|
|
495
471
|
|
|
@@ -539,9 +539,7 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
539
539
|
try:
|
|
540
540
|
system_prompt_with_time = await enricher(
|
|
541
541
|
system_prompt_with_time,
|
|
542
|
-
message.from_user.id
|
|
543
|
-
session_id,
|
|
544
|
-
supabase_client
|
|
542
|
+
message.from_user.id
|
|
545
543
|
)
|
|
546
544
|
logger.info(f"✅ Промпт обогащен '{enricher.__name__}'")
|
|
547
545
|
except Exception as e:
|
|
@@ -567,9 +565,7 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
567
565
|
for enricher in context_enrichers:
|
|
568
566
|
try:
|
|
569
567
|
messages = await enricher(
|
|
570
|
-
messages
|
|
571
|
-
message.from_user.id,
|
|
572
|
-
session_id
|
|
568
|
+
messages
|
|
573
569
|
)
|
|
574
570
|
logger.info(f"✅ Контекст обогащен '{enricher.__name__}'")
|
|
575
571
|
except Exception as e:
|
|
@@ -628,19 +624,6 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
628
624
|
|
|
629
625
|
logger.info(f"✅ Финальный текст для отправки: {len(response_text)} символов")
|
|
630
626
|
|
|
631
|
-
# ============ ХУК 4: ОБРАБОТКА ОТВЕТА ============
|
|
632
|
-
response_processors = message_hooks.get('response_processors', [])
|
|
633
|
-
for processor in response_processors:
|
|
634
|
-
try:
|
|
635
|
-
response_text, ai_metadata = await processor(
|
|
636
|
-
response_text,
|
|
637
|
-
ai_metadata,
|
|
638
|
-
message.from_user.id
|
|
639
|
-
)
|
|
640
|
-
logger.info(f"✅ Ответ обработан '{processor.__name__}'")
|
|
641
|
-
except Exception as e:
|
|
642
|
-
logger.error(f"❌ Ошибка в обработчике ответа '{processor.__name__}': {e}")
|
|
643
|
-
|
|
644
627
|
# Обновляем этап сессии и качество лида
|
|
645
628
|
if ai_metadata:
|
|
646
629
|
logger.info("🔍 Анализ метаданных от ИИ:")
|
|
@@ -749,7 +732,7 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
749
732
|
|
|
750
733
|
logger.info(f"📱 Отправляем пользователю: {len(final_response)} символов")
|
|
751
734
|
|
|
752
|
-
# ============ ХУК
|
|
735
|
+
# ============ ХУК 4: ФИЛЬТРЫ ОТПРАВКИ ============
|
|
753
736
|
send_filters = message_hooks.get('send_filters', [])
|
|
754
737
|
for filter_func in send_filters:
|
|
755
738
|
try:
|
|
@@ -7,10 +7,12 @@ from ..core.message_sender import (
|
|
|
7
7
|
send_message_by_human,
|
|
8
8
|
send_message_by_ai,
|
|
9
9
|
send_message_to_users_by_stage,
|
|
10
|
+
send_message,
|
|
10
11
|
)
|
|
11
12
|
|
|
12
13
|
__all__ = [
|
|
13
14
|
'send_message_by_human',
|
|
14
15
|
'send_message_by_ai',
|
|
15
16
|
'send_message_to_users_by_stage',
|
|
17
|
+
'send_message', # Чистая отправка с файлами и кнопками
|
|
16
18
|
]
|
|
@@ -27,29 +27,29 @@ smart_bot_factory/configs/growthmed-october-24/welcome_file/Чек лист по
|
|
|
27
27
|
smart_bot_factory/core/bot_utils.py,sha256=XmwQ31LOpE_Wudx4OO4tlnVwse3YagakwpgN2cZC5SQ,41085
|
|
28
28
|
smart_bot_factory/core/conversation_manager.py,sha256=eoHL7MCEz68DRvTVwRwZgf2PWwGv4T6J9D-I-thETi8,28289
|
|
29
29
|
smart_bot_factory/core/decorators.py,sha256=xQCtr5SOLqqmEzaxrDf_sfxWQouIG7riI6Sa_jqGlcg,68647
|
|
30
|
-
smart_bot_factory/core/message_sender.py,sha256=
|
|
30
|
+
smart_bot_factory/core/message_sender.py,sha256=J4b6n8nXVjqf-qzL6URRSvc-FVnQfShwujVSM6qv26w,32232
|
|
31
31
|
smart_bot_factory/core/router.py,sha256=o-AzLarBgYbXq7OeeXQEfa6XFqcAtLKqf5-3Do79Boo,11555
|
|
32
32
|
smart_bot_factory/core/router_manager.py,sha256=dUwesog-oHk1U2EDdS8p0e4MTSkwtx5_qXn6nrJ9l9I,9700
|
|
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=
|
|
36
|
+
smart_bot_factory/creation/bot_builder.py,sha256=vMvjq6deCD_TjkQfAyTlFF1FNXxzA-W0SloLObPK4_M,32620
|
|
37
37
|
smart_bot_factory/creation/bot_testing.py,sha256=JDWXyJfZmbgo-DLdAPk8Sd9FiehtHHa4sLD17lBrTOc,55669
|
|
38
|
-
smart_bot_factory/database/database_structure.sql,sha256=26gFtMC2jdQGQF7Zb_F4Br56rMd4hUDTk9FkNZYneLo,2789
|
|
39
|
-
smart_bot_factory/database/schema.sql,sha256=-6kOmA9QnSkUtmGI2iQRbTvbdiqOhEOQcuz1lJn79mU,28059
|
|
40
38
|
smart_bot_factory/event/__init__.py,sha256=hPL449RULIOB-OXv1ZbGNiHctAYaOMUqhSWGPrDHYBM,212
|
|
41
|
-
smart_bot_factory/handlers/handlers.py,sha256=
|
|
39
|
+
smart_bot_factory/handlers/handlers.py,sha256=BZ9KSFnudVg3iU_XuNI0hter7ZOl9Kc6P4TyLwPh0AM,40803
|
|
42
40
|
smart_bot_factory/integrations/openai_client.py,sha256=aMcDrKO0GEx3ZSVEOGDeDtFCDWSXs6biUfgrbRK8yTU,23180
|
|
43
41
|
smart_bot_factory/integrations/supabase_client.py,sha256=AfALLZdDYeMWHLJw6POTGiBd-sH3i03oT6tT7m9C28I,44644
|
|
44
|
-
smart_bot_factory/message/__init__.py,sha256=
|
|
42
|
+
smart_bot_factory/message/__init__.py,sha256=8XWEEl3J0l1xDeEPmXPwFbHbnQelGApCwnicUkcBbOg,391
|
|
45
43
|
smart_bot_factory/router/__init__.py,sha256=QrfO5u8H2uVzWGMtBvNKunsJAv7UrKtvt2f_D5xSFWE,270
|
|
46
44
|
smart_bot_factory/supabase/__init__.py,sha256=XmZP6yM9ffERM5ddAWyJnrNzEhCYtMu3AcjVCi1rOf8,179
|
|
47
45
|
smart_bot_factory/supabase/client.py,sha256=8_-I3kxZQlKQElI4cTUjNGYcqlyIyEkSrUZaP0nfNNU,26044
|
|
46
|
+
smart_bot_factory/table/database_structure.sql,sha256=26gFtMC2jdQGQF7Zb_F4Br56rMd4hUDTk9FkNZYneLo,2789
|
|
47
|
+
smart_bot_factory/table/schema.sql,sha256=-6kOmA9QnSkUtmGI2iQRbTvbdiqOhEOQcuz1lJn79mU,28059
|
|
48
48
|
smart_bot_factory/utils/__init__.py,sha256=5zNjw491bj5VkOhoEAwh2hjmv8nldyDOTrG7pbGpz6A,285
|
|
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.
|
|
52
|
-
smart_bot_factory-0.2.
|
|
53
|
-
smart_bot_factory-0.2.
|
|
54
|
-
smart_bot_factory-0.2.
|
|
55
|
-
smart_bot_factory-0.2.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|