smart-bot-factory 0.3.1__py3-none-any.whl → 0.3.2__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.

@@ -5,7 +5,7 @@ import time
5
5
  from aiogram import Router, F
6
6
  from aiogram.filters import Command, StateFilter
7
7
  from aiogram.fsm.context import FSMContext
8
- from aiogram.types import Message
8
+ from aiogram.types import Message, CallbackQuery
9
9
 
10
10
  from ..core.bot_utils import send_message, parse_ai_response, process_events, send_welcome_file
11
11
  from ..core.states import UserStates, AdminStates
@@ -172,7 +172,153 @@ async def timeup_handler(message: Message, state: FSMContext):
172
172
  except Exception as e:
173
173
  logger.error(f"❌ Критическая ошибка в timeup_handler: {e}")
174
174
  await message.answer(f"❌ Ошибка тестирования: {str(e)}")
175
-
175
+
176
+ @router.message(F.voice | F.audio)
177
+ async def voice_handler(message: Message, state: FSMContext):
178
+ """Обработчик голосовых и аудио сообщений"""
179
+ openai_client = get_global_var('openai_client')
180
+ bot = get_global_var('bot')
181
+ admin_manager = get_global_var('admin_manager')
182
+
183
+ import os
184
+ from pathlib import Path
185
+ from datetime import datetime
186
+
187
+ processing_msg = None
188
+
189
+ try:
190
+ # Проверяем что это не админ в режиме администратора
191
+ if admin_manager.is_admin(message.from_user.id):
192
+ if admin_manager.is_in_admin_mode(message.from_user.id):
193
+ return # Админы работают с текстом
194
+
195
+ logger.info(f"🎤 Получено голосовое сообщение от {message.from_user.id}")
196
+
197
+ # Получаем файл
198
+ if message.voice:
199
+ file_id = message.voice.file_id
200
+ duration = message.voice.duration
201
+ else:
202
+ file_id = message.audio.file_id
203
+ duration = message.audio.duration
204
+
205
+ # Показываем что обрабатываем
206
+ processing_msg = await message.answer("🎤 Распознаю голос...")
207
+
208
+ try:
209
+ # Скачиваем файл
210
+ file = await bot.get_file(file_id)
211
+
212
+ # Путь для сохранения
213
+ temp_dir = Path("temp_audio")
214
+ temp_dir.mkdir(exist_ok=True)
215
+
216
+ file_path = temp_dir / f"{message.from_user.id}_{int(datetime.now().timestamp())}.ogg"
217
+
218
+ # Скачиваем
219
+ await bot.download_file(file.file_path, file_path)
220
+ logger.info(f"📥 Файл скачан: {file_path} ({duration} сек)")
221
+
222
+ # Распознаем через Whisper
223
+ recognized_text = await openai_client.transcribe_audio(str(file_path))
224
+
225
+ # Удаляем временный файл
226
+ try:
227
+ os.remove(file_path)
228
+ logger.info(f"🗑️ Временный файл удален: {file_path}")
229
+ except Exception as e:
230
+ logger.warning(f"⚠️ Не удалось удалить временный файл: {e}")
231
+
232
+ if not recognized_text:
233
+ await processing_msg.edit_text("❌ Не удалось распознать голос. Попробуйте еще раз.")
234
+ return
235
+
236
+ logger.info(f"✅ Текст распознан успешно: '{recognized_text[:100]}...'")
237
+
238
+ # Получаем данные сессии
239
+ current_state = await state.get_state()
240
+ data = await state.get_data()
241
+
242
+ logger.info(f"🔍 Текущее состояние: {current_state}")
243
+ logger.info(f"🔍 Данные в state: {data}")
244
+
245
+ session_id = data.get('session_id')
246
+ system_prompt = data.get('system_prompt')
247
+
248
+ logger.info(f"📝 session_id из state: {session_id}")
249
+
250
+ # Если session_id нет в state, пытаемся получить из БД
251
+ if not session_id:
252
+ logger.warning(f"⚠️ session_id не найден в state, ищем активную сессию в БД...")
253
+ supabase_client = get_global_var('supabase_client')
254
+
255
+ session_info = await supabase_client.get_active_session(message.from_user.id)
256
+ if session_info:
257
+ session_id = session_info['id']
258
+ system_prompt = session_info['system_prompt']
259
+
260
+ # Сохраняем в state для следующих сообщений
261
+ await state.update_data(session_id=session_id, system_prompt=system_prompt)
262
+ await state.set_state(UserStates.waiting_for_message)
263
+
264
+ logger.info(f"✅ Сессия восстановлена из БД: {session_id}")
265
+ else:
266
+ logger.error(f"❌ Активная сессия не найдена в БД")
267
+
268
+ if session_id:
269
+ # Сохраняем распознанный текст в state
270
+ await state.update_data(voice_recognized_text=recognized_text)
271
+ await state.set_state(UserStates.voice_confirmation)
272
+
273
+ # Показываем распознанный текст с кнопками выбора
274
+ from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
275
+
276
+ keyboard = InlineKeyboardMarkup(inline_keyboard=[
277
+ [InlineKeyboardButton(text="✅ Отправить", callback_data="voice_send")],
278
+ [InlineKeyboardButton(text="✏️ Изменить текст", callback_data="voice_edit")],
279
+ [InlineKeyboardButton(text="🎤 Надиктовать заново", callback_data="voice_retry")]
280
+ ])
281
+
282
+ # Удаляем сообщение "Обрабатываю"
283
+ try:
284
+ await processing_msg.delete()
285
+ except:
286
+ pass
287
+
288
+ # Показываем результат с кнопками
289
+ await message.answer(
290
+ f"✅ Распознано:\n\n<i>{recognized_text}</i>\n\n"
291
+ f"Выберите действие:",
292
+ reply_markup=keyboard,
293
+ parse_mode='HTML'
294
+ )
295
+
296
+ logger.info(f"✅ Показаны кнопки подтверждения голосового сообщения")
297
+ else:
298
+ logger.warning(f"❌ Нет session_id в состоянии")
299
+ await processing_msg.edit_text(
300
+ f"✅ Распознано:\n\n{recognized_text}\n\n"
301
+ f"Сессия не найдена. Напишите /start"
302
+ )
303
+
304
+ except Exception as e:
305
+ logger.error(f"❌ Ошибка в процессе обработки голоса: {e}")
306
+ logger.exception("Полный стек ошибки:")
307
+ if processing_msg:
308
+ await processing_msg.edit_text("❌ Ошибка обработки. Попробуйте написать текстом.")
309
+ else:
310
+ await message.answer("❌ Ошибка обработки. Попробуйте написать текстом.")
311
+
312
+ except Exception as e:
313
+ logger.error(f"❌ КРИТИЧЕСКАЯ ошибка обработки голоса: {e}")
314
+ logger.exception("Полный стек критической ошибки:")
315
+ try:
316
+ if processing_msg:
317
+ await processing_msg.edit_text("❌ Ошибка распознавания. Попробуйте написать текстом.")
318
+ else:
319
+ await message.answer("❌ Ошибка распознавания. Попробуйте написать текстом.")
320
+ except:
321
+ pass
176
322
 
177
323
  async def user_start_handler(message: Message, state: FSMContext):
178
324
  """Обработчик /start для обычных пользователей"""
@@ -465,6 +611,112 @@ async def user_message_handler(message: Message, state: FSMContext):
465
611
  except Exception as e:
466
612
  logger.error(f"❌ Ошибка при обработке сообщения пользователя: {e}")
467
613
  await send_message(message, "Произошла ошибка. Попробуйте еще раз или напишите /start для перезапуска.")
614
+
615
+ @router.callback_query(F.data == "voice_send")
616
+ async def voice_send_handler(callback: CallbackQuery, state: FSMContext):
617
+ """Обработчик кнопки 'Отправить' для голосового сообщения"""
618
+ try:
619
+ data = await state.get_data()
620
+ recognized_text = data.get('voice_recognized_text')
621
+ session_id = data.get('session_id')
622
+ system_prompt = data.get('system_prompt')
623
+
624
+ if not recognized_text or not session_id:
625
+ await callback.answer("❌ Ошибка: текст не найден", show_alert=True)
626
+ return
627
+
628
+ # Удаляем сообщение с кнопками
629
+ await callback.message.delete()
630
+
631
+ # Обрабатываем текст сразу без промежуточного сообщения
632
+ await process_voice_message(callback.message, state, session_id, system_prompt, recognized_text)
633
+
634
+ # Возвращаем в обычное состояние
635
+ await state.set_state(UserStates.waiting_for_message)
636
+ await state.update_data(voice_recognized_text=None)
637
+
638
+ await callback.answer()
639
+
640
+ except Exception as e:
641
+ logger.error(f"❌ Ошибка отправки голосового: {e}")
642
+ await callback.answer("❌ Ошибка обработки", show_alert=True)
643
+
644
+ @router.callback_query(F.data == "voice_edit")
645
+ async def voice_edit_handler(callback: CallbackQuery, state: FSMContext):
646
+ """Обработчик кнопки 'Изменить текст' для голосового сообщения"""
647
+ try:
648
+ data = await state.get_data()
649
+ recognized_text = data.get('voice_recognized_text')
650
+
651
+ if not recognized_text:
652
+ await callback.answer("❌ Ошибка: текст не найден", show_alert=True)
653
+ return
654
+
655
+ # Переводим в режим редактирования
656
+ await state.set_state(UserStates.voice_editing)
657
+
658
+ # Показываем текст для редактирования (обычный формат)
659
+ await callback.message.edit_text(
660
+ f"✏️ Отредактируйте распознанный текст:\n\n"
661
+ f"{recognized_text}\n\n"
662
+ f"Напишите исправленный текст:"
663
+ )
664
+
665
+ await callback.answer()
666
+
667
+ except Exception as e:
668
+ logger.error(f"❌ Ошибка редактирования: {e}")
669
+ await callback.answer("❌ Ошибка", show_alert=True)
670
+
671
+ @router.callback_query(F.data == "voice_retry")
672
+ async def voice_retry_handler(callback: CallbackQuery, state: FSMContext):
673
+ """Обработчик кнопки 'Надиктовать заново' для голосового сообщения"""
674
+ try:
675
+ # Удаляем сообщение с кнопками
676
+ await callback.message.delete()
677
+
678
+ # Возвращаем в обычное состояние
679
+ await state.set_state(UserStates.waiting_for_message)
680
+ await state.update_data(voice_recognized_text=None)
681
+
682
+ # Просим отправить заново
683
+ await callback.message.answer("🎤 Отправьте голосовое сообщение заново")
684
+
685
+ await callback.answer()
686
+
687
+ except Exception as e:
688
+ logger.error(f"❌ Ошибка повтора: {e}")
689
+ await callback.answer("❌ Ошибка", show_alert=True)
690
+
691
+ @router.message(StateFilter(UserStates.voice_editing))
692
+ async def voice_edit_text_handler(message: Message, state: FSMContext):
693
+ """Обработчик получения отредактированного текста"""
694
+ try:
695
+ edited_text = message.text.strip()
696
+
697
+ if not edited_text:
698
+ await message.answer("⚠️ Текст не может быть пустым. Напишите текст:")
699
+ return
700
+
701
+ # Получаем данные сессии
702
+ data = await state.get_data()
703
+ session_id = data.get('session_id')
704
+ system_prompt = data.get('system_prompt')
705
+
706
+ if not session_id:
707
+ await message.answer("❌ Сессия не найдена. Напишите /start")
708
+ return
709
+
710
+ # Обрабатываем отредактированный текст сразу
711
+ await process_voice_message(message, state, session_id, system_prompt, edited_text)
712
+
713
+ # Возвращаем в обычное состояние
714
+ await state.set_state(UserStates.waiting_for_message)
715
+ await state.update_data(voice_recognized_text=None)
716
+
717
+ except Exception as e:
718
+ logger.error(f"❌ Ошибка обработки отредактированного текста: {e}")
719
+ await message.answer("❌ Ошибка обработки. Попробуйте еще раз или напишите /start")
468
720
 
469
721
  @router.message()
470
722
  async def catch_all_handler(message: Message, state: FSMContext):
@@ -778,4 +1030,135 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
778
1030
  try:
779
1031
  await message.answer("Произошла критическая ошибка. Попробуйте написать /start для перезапуска.")
780
1032
  except:
781
- logger.error(f"❌ Не удалось отправить сообщение об критической ошибке")
1033
+ logger.error(f"❌ Не удалось отправить сообщение об критической ошибке")
1034
+
1035
+ async def process_voice_message(message: Message, state: FSMContext, session_id: str, system_prompt: str, recognized_text: str):
1036
+ """Обработка распознанного голосового сообщения"""
1037
+ supabase_client = get_global_var('supabase_client')
1038
+ openai_client = get_global_var('openai_client')
1039
+ config = get_global_var('config')
1040
+ bot = get_global_var('bot')
1041
+ prompt_loader = get_global_var('prompt_loader')
1042
+
1043
+ from datetime import datetime
1044
+ import pytz
1045
+
1046
+ try:
1047
+ # Сохраняем распознанное сообщение как текст пользователя
1048
+ await supabase_client.add_message(
1049
+ session_id=session_id,
1050
+ role='user',
1051
+ content=recognized_text,
1052
+ message_type='text', # БД разрешает только 'text'
1053
+ metadata={'original_type': 'voice', 'duration': message.voice.duration if message.voice else 0}
1054
+ )
1055
+ logger.info(f"✅ Распознанное сообщение сохранено в БД")
1056
+
1057
+ # Получаем историю сообщений
1058
+ chat_history = await supabase_client.get_chat_history(session_id, limit=config.MAX_CONTEXT_MESSAGES)
1059
+ logger.info(f"📚 Загружена история: {len(chat_history)} сообщений")
1060
+
1061
+ # Добавляем текущее время
1062
+ moscow_tz = pytz.timezone('Europe/Moscow')
1063
+ current_time = datetime.now(moscow_tz)
1064
+ time_info = current_time.strftime('%H:%M, %d.%m.%Y, %A')
1065
+
1066
+ system_prompt_with_time = f"""
1067
+ {system_prompt}
1068
+
1069
+ ТЕКУЩЕЕ ВРЕМЯ: {time_info} (московское время)
1070
+ """
1071
+
1072
+ # Формируем контекст для OpenAI
1073
+ messages = [{"role": "system", "content": system_prompt_with_time}]
1074
+
1075
+ for msg in chat_history[-config.MAX_CONTEXT_MESSAGES:]:
1076
+ messages.append({
1077
+ "role": msg['role'],
1078
+ "content": msg['content']
1079
+ })
1080
+
1081
+ # Добавляем финальные инструкции
1082
+ final_instructions = await prompt_loader.load_final_instructions()
1083
+ if final_instructions:
1084
+ messages.append({"role": "system", "content": final_instructions})
1085
+ logger.info(f"🎯 Добавлены финальные инструкции")
1086
+
1087
+ logger.info(f"📝 Контекст сформирован: {len(messages)} сообщений")
1088
+
1089
+ await bot.send_chat_action(message.chat.id, "typing")
1090
+
1091
+ import time
1092
+ start_time = time.time()
1093
+ ai_response = await openai_client.get_completion(messages)
1094
+ processing_time = int((time.time() - start_time) * 1000)
1095
+
1096
+ logger.info(f"🤖 OpenAI ответил за {processing_time}мс")
1097
+
1098
+ tokens_used = 0
1099
+ ai_metadata = {}
1100
+ response_text = ""
1101
+
1102
+ if not ai_response or not ai_response.strip():
1103
+ logger.warning(f"❌ OpenAI вернул пустой ответ!")
1104
+ fallback_message = "Извините, произошла техническая ошибка. Попробуйте еще раз."
1105
+ ai_response = fallback_message
1106
+ response_text = fallback_message
1107
+ tokens_used = 0
1108
+ ai_metadata = {}
1109
+ else:
1110
+ tokens_used = openai_client.estimate_tokens(ai_response)
1111
+ response_text, ai_metadata = parse_ai_response(ai_response)
1112
+
1113
+ if not ai_metadata:
1114
+ response_text = ai_response
1115
+ ai_metadata = {}
1116
+ elif not response_text.strip():
1117
+ logger.warning("⚠️ JSON найден, но текст пустой! Используем исходный ответ.")
1118
+ response_text = ai_response
1119
+
1120
+ # Обновляем этап и качество
1121
+ if ai_metadata:
1122
+ stage = ai_metadata.get('этап')
1123
+ quality = ai_metadata.get('качество')
1124
+
1125
+ if stage or quality is not None:
1126
+ await supabase_client.update_session_stage(session_id, stage, quality)
1127
+
1128
+ # Обрабатываем события
1129
+ events = ai_metadata.get('события', [])
1130
+ if events:
1131
+ await process_events(session_id, events, message.from_user.id)
1132
+
1133
+ # Сохраняем ответ ассистента
1134
+ await supabase_client.add_message(
1135
+ session_id=session_id,
1136
+ role='assistant',
1137
+ content=response_text,
1138
+ message_type='text',
1139
+ tokens_used=tokens_used,
1140
+ processing_time_ms=processing_time,
1141
+ ai_metadata=ai_metadata
1142
+ )
1143
+
1144
+ # Определяем финальный ответ
1145
+ final_response = ai_response if config.DEBUG_MODE else response_text
1146
+
1147
+ if not final_response or not final_response.strip():
1148
+ final_response = "Извините, произошла ошибка при формировании ответа. Попробуйте еще раз."
1149
+
1150
+ # Обрабатываем файлы
1151
+ files_list = ai_metadata.get('файлы', [])
1152
+ directories_list = ai_metadata.get('каталоги', [])
1153
+
1154
+ # Отправляем ответ пользователю
1155
+ await send_message(message, final_response, files_list=files_list, directories_list=directories_list)
1156
+ logger.info(f"✅ Ответ отправлен пользователю {message.from_user.id}")
1157
+
1158
+ except Exception as e:
1159
+ logger.error(f"❌ КРИТИЧЕСКАЯ ОШИБКА в process_voice_message: {e}")
1160
+ logger.exception("Полный стек ошибки:")
1161
+ try:
1162
+ await message.answer("Произошла критическая ошибка. Попробуйте написать /start")
1163
+ except:
1164
+ pass
@@ -432,4 +432,32 @@ class OpenAIClient:
432
432
  return [model.id for model in models.data if 'gpt' in model.id.lower()]
433
433
  except Exception as e:
434
434
  logger.error(f"Ошибка при получении списка моделей: {e}")
435
- return []
435
+ return []
436
+
437
+ async def transcribe_audio(self, audio_file_path: str) -> str:
438
+ """
439
+ Распознает голосовое сообщение через Whisper API
440
+
441
+ Args:
442
+ audio_file_path: Путь к аудио файлу
443
+
444
+ Returns:
445
+ Распознанный текст
446
+ """
447
+ try:
448
+ logger.info(f"🎤 Отправка аудио на распознавание: {audio_file_path}")
449
+
450
+ with open(audio_file_path, 'rb') as audio_file:
451
+ transcript = await self.client.audio.transcriptions.create(
452
+ model="whisper-1",
453
+ file=audio_file,
454
+ language="ru" # Русский язык
455
+ )
456
+
457
+ text = transcript.text
458
+ logger.info(f"✅ Распознано {len(text)} символов: '{text[:100]}...'")
459
+ return text
460
+
461
+ except Exception as e:
462
+ logger.error(f"❌ Ошибка распознавания аудио: {e}")
463
+ return ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart-bot-factory
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Библиотека для создания умных чат-ботов
5
5
  Author-email: Kopatych <eserov73@gmail.com>
6
6
  License: MIT
@@ -33,27 +33,27 @@ Description-Content-Type: text/markdown
33
33
 
34
34
  # Smart Bot Factory
35
35
 
36
- **Библиотека для создания умных Telegram ботов с AI, аналитикой и гибкой архитектурой**
36
+ ## Библиотека для создания умных Telegram ботов с AI, аналитикой и гибкой архитектурой
37
37
 
38
38
  ## 📋 Содержание
39
39
 
40
- - [Установка](#установка)
41
- - [Быстрый старт](#быстрый-старт)
42
- - [CLI Команды](#cli-команды)
43
- - [Декораторы](#декораторы)
40
+ - [Установка](#-установка)
41
+ - [Быстрый старт](#-быстрый-старт)
42
+ - [CLI Команды](#-cli-команды)
43
+ - [Декораторы](#-декораторы)
44
44
  - [event_handler](#event_handler---обработчики-событий)
45
45
  - [schedule_task](#schedule_task---запланированные-задачи)
46
46
  - [global_handler](#global_handler---глобальные-обработчики)
47
- - [Хуки для кастомизации](#хуки-для-кастомизации)
48
- - [Telegram роутеры](#telegram-роутеры)
49
- - [Расширенные возможности](#расширенные-возможности)
47
+ - [Хуки для кастомизации](#-хуки-для-кастомизации)
48
+ - [Telegram роутеры](#-telegram-роутеры)
49
+ - [Расширенные возможности](#-расширенные-возможности)
50
50
 
51
51
  ---
52
52
 
53
53
  ## 🚀 Установка
54
54
 
55
55
  ```bash
56
- pip install smart-bot-factory
56
+ pip install smart_bot_factory
57
57
  ```
58
58
 
59
59
  ## ⚡ Быстрый старт
@@ -112,10 +112,18 @@ if __name__ == "__main__":
112
112
  # Создать нового бота из базового шаблона
113
113
  sbf create my-bot
114
114
 
115
- # Создать из кастомного шаблона
116
- sbf create new-bot existing-bot
115
+ # Скопировать существующего бота
116
+ sbf copy best-valera new-valera
117
+
117
118
  ```
118
119
 
120
+ **💡 Команда `copy` - создает нового бота на основе существующего:**
121
+
122
+ - ✅ Копирует код бота с автозаменой `bot_id`
123
+ - ✅ Копирует все промпты
124
+ - ✅ Копирует тесты и файлы
125
+ - ✅ Создает новый `.env` (не копирует токены)
126
+
119
127
  ### Управление ботами
120
128
 
121
129
  ```bash
@@ -268,7 +276,7 @@ async def handler(user_id: int, user_data: str):
268
276
 
269
277
  **Формула времени с `event_type`:**
270
278
 
271
- ```
279
+ ```text
272
280
  reminder_time = event_datetime - delay
273
281
  ```
274
282
 
@@ -622,8 +630,8 @@ from smart_bot_factory.message import send_message
622
630
  async def send_catalog(user_id: int, event_data: str):
623
631
  """Отправляет каталог с файлами"""
624
632
  from smart_bot_factory.message import get_bot
625
- from smart_bot_factory.supabase import SupabaseClient
626
-
633
+ from smart_bot_factory.supabase import SupabaseClient
634
+
627
635
  bot = get_bot()
628
636
  supabase_client = SupabaseClient("my-bot")
629
637
 
@@ -761,7 +769,7 @@ if __name__ == "__main__":
761
769
 
762
770
  ## 📖 Структура проекта
763
771
 
764
- ```
772
+ ```text
765
773
  project/
766
774
  ├── bots/
767
775
  │ └── my-bot/
@@ -781,7 +789,7 @@ project/
781
789
 
782
790
  ## ⚙️ Конфигурация (.env)
783
791
 
784
- ```env
792
+ ```bash
785
793
  # Telegram
786
794
  TELEGRAM_BOT_TOKEN=your_token_here
787
795
 
@@ -35,8 +35,8 @@ smart_bot_factory/creation/__init__.py,sha256=IgDk8GDS3pg7Pw_Et41J33ZmeZIU5dRwQd
35
35
  smart_bot_factory/creation/bot_builder.py,sha256=KQmMmiL9OuGZAR3rYxMNk-2opMUR5NPRy9Sf9iVNCoU,39463
36
36
  smart_bot_factory/creation/bot_testing.py,sha256=JDWXyJfZmbgo-DLdAPk8Sd9FiehtHHa4sLD17lBrTOc,55669
37
37
  smart_bot_factory/event/__init__.py,sha256=hPL449RULIOB-OXv1ZbGNiHctAYaOMUqhSWGPrDHYBM,212
38
- smart_bot_factory/handlers/handlers.py,sha256=HbD26bt-VpqXQ5nwRXeU3n0A4tGNTHmR-VyuFur5D6k,41709
39
- smart_bot_factory/integrations/openai_client.py,sha256=aMcDrKO0GEx3ZSVEOGDeDtFCDWSXs6biUfgrbRK8yTU,23180
38
+ smart_bot_factory/handlers/handlers.py,sha256=urTUYSqK9zDxomFbC056gN5T4o7Gz9gN0bm84DPzvVc,60390
39
+ smart_bot_factory/integrations/openai_client.py,sha256=fwaJpwojFdLBWChcFWpFGOHK9upG-nCIwDochkCRRlY,24291
40
40
  smart_bot_factory/integrations/supabase_client.py,sha256=AfALLZdDYeMWHLJw6POTGiBd-sH3i03oT6tT7m9C28I,44644
41
41
  smart_bot_factory/message/__init__.py,sha256=-ehDZweUc3uKgmLLxFVsD-KWrDtnHpHms7pCrDelWo0,1950
42
42
  smart_bot_factory/router/__init__.py,sha256=5gEbpG3eylOyow5NmidzGUy0K-AZq7RhYLVu9OaUT6c,270
@@ -48,8 +48,8 @@ smart_bot_factory/utils/__init__.py,sha256=UhsJXEHfrIK8h1AHsroHSwAriijk-LvnqLyvg
48
48
  smart_bot_factory/utils/debug_routing.py,sha256=BOoDhKBg7UXe5uHQxRk3TSfPfLPOFqt0N7lAo6kjCOo,4719
49
49
  smart_bot_factory/utils/prompt_loader.py,sha256=JSn7CsWnToSbHYtURdeuZn7ectyDqQGrPGHN2ixIGkw,19930
50
50
  smart_bot_factory/utils/user_prompt_loader.py,sha256=dk6P0X_3UcNqxjRtuIvb0LcPrp03zIIsstZwdmeCPaE,2519
51
- smart_bot_factory-0.3.1.dist-info/METADATA,sha256=yL4hSPAe4vYlsSJ5YLTs9ic6I7_Ic13Rn9bFWfo8JJc,31533
52
- smart_bot_factory-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
- smart_bot_factory-0.3.1.dist-info/entry_points.txt,sha256=ybKEAI0WSb7WoRiey7QE-HHfn88UGV7nxLDxXq7b7SU,50
54
- smart_bot_factory-0.3.1.dist-info/licenses/LICENSE,sha256=OrK3cwdUTzNzIhJvSPtJaVMoYIyC_sSx5EFE_FDMvGs,1092
55
- smart_bot_factory-0.3.1.dist-info/RECORD,,
51
+ smart_bot_factory-0.3.2.dist-info/METADATA,sha256=alPg424Y9-vgxD2LUovu3EJJNMLlxuTqEPXukWJBw0c,31905
52
+ smart_bot_factory-0.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
+ smart_bot_factory-0.3.2.dist-info/entry_points.txt,sha256=ybKEAI0WSb7WoRiey7QE-HHfn88UGV7nxLDxXq7b7SU,50
54
+ smart_bot_factory-0.3.2.dist-info/licenses/LICENSE,sha256=OrK3cwdUTzNzIhJvSPtJaVMoYIyC_sSx5EFE_FDMvGs,1092
55
+ smart_bot_factory-0.3.2.dist-info/RECORD,,