smart-bot-factory 0.3.1__tar.gz → 0.3.2__tar.gz
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-0.3.1 → smart_bot_factory-0.3.2}/PKG-INFO +25 -17
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/README.md +24 -16
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/pyproject.toml +1 -1
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/handlers/handlers.py +386 -3
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/integrations/openai_client.py +29 -1
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/uv.lock +1 -1
- smart_bot_factory-0.3.1/.github/ISSUE_TEMPLATE//342/234/250-/320/267/320/260/320/277/321/200/320/276/321/201-/321/204/321/203/320/275/320/272/321/206/320/270/320/270.md +0 -20
- smart_bot_factory-0.3.1/.github/ISSUE_TEMPLATE//360/237/220/233-/320/261/320/260/320/263-/321/200/320/265/320/277/320/276/321/200/321/202.md +0 -26
- smart_bot_factory-0.3.1/.github/workflows/ci.yml +0 -59
- smart_bot_factory-0.3.1/.github/workflows/publish-private.yml +0 -34
- smart_bot_factory-0.3.1/.github/workflows/publish.yml +0 -31
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/.gitignore +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/.python-version +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/LICENSE +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/best-valera.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/welcome_files/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/welcome_files//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/welcome_files/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/welcome_files//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/publish.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_logic.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_manager.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_migration.sql +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_tester.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/timeout_checker.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/analytics/analytics_manager.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/cli.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/config.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064229.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064335.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064638.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/configs/growthmed-october-24/welcome_file//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/bot_utils.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/conversation_manager.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/decorators.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/message_sender.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/router.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/router_manager.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/states.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/creation/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/creation/bot_builder.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/creation/bot_testing.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/event/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/integrations/supabase_client.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/message/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/router/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/setup_checker.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/supabase/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/supabase/client.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/table/database_structure.sql +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/table/schema.sql +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/__init__.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/debug_routing.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/prompt_loader.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/user_prompt_loader.py +0 -0
- {smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utm_link_generator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: smart-bot-factory
|
|
3
|
-
Version: 0.3.
|
|
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
|
-
|
|
36
|
+
## Библиотека для создания умных Telegram ботов с AI, аналитикой и гибкой архитектурой
|
|
37
37
|
|
|
38
38
|
## 📋 Содержание
|
|
39
39
|
|
|
40
|
-
- [Установка](
|
|
41
|
-
- [Быстрый старт](
|
|
42
|
-
- [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 роутеры](
|
|
49
|
-
- [Расширенные возможности](
|
|
47
|
+
- [Хуки для кастомизации](#-хуки-для-кастомизации)
|
|
48
|
+
- [Telegram роутеры](#-telegram-роутеры)
|
|
49
|
+
- [Расширенные возможности](#-расширенные-возможности)
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
53
53
|
## 🚀 Установка
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
pip install
|
|
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
|
|
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
|
-
|
|
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
|
-
```
|
|
792
|
+
```bash
|
|
785
793
|
# Telegram
|
|
786
794
|
TELEGRAM_BOT_TOKEN=your_token_here
|
|
787
795
|
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# Smart Bot Factory
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Библиотека для создания умных Telegram ботов с AI, аналитикой и гибкой архитектурой
|
|
4
4
|
|
|
5
5
|
## 📋 Содержание
|
|
6
6
|
|
|
7
|
-
- [Установка](
|
|
8
|
-
- [Быстрый старт](
|
|
9
|
-
- [CLI Команды](
|
|
10
|
-
- [Декораторы](
|
|
7
|
+
- [Установка](#-установка)
|
|
8
|
+
- [Быстрый старт](#-быстрый-старт)
|
|
9
|
+
- [CLI Команды](#-cli-команды)
|
|
10
|
+
- [Декораторы](#-декораторы)
|
|
11
11
|
- [event_handler](#event_handler---обработчики-событий)
|
|
12
12
|
- [schedule_task](#schedule_task---запланированные-задачи)
|
|
13
13
|
- [global_handler](#global_handler---глобальные-обработчики)
|
|
14
|
-
- [Хуки для кастомизации](
|
|
15
|
-
- [Telegram роутеры](
|
|
16
|
-
- [Расширенные возможности](
|
|
14
|
+
- [Хуки для кастомизации](#-хуки-для-кастомизации)
|
|
15
|
+
- [Telegram роутеры](#-telegram-роутеры)
|
|
16
|
+
- [Расширенные возможности](#-расширенные-возможности)
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
## 🚀 Установка
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
pip install
|
|
23
|
+
pip install smart_bot_factory
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## ⚡ Быстрый старт
|
|
@@ -79,10 +79,18 @@ if __name__ == "__main__":
|
|
|
79
79
|
# Создать нового бота из базового шаблона
|
|
80
80
|
sbf create my-bot
|
|
81
81
|
|
|
82
|
-
#
|
|
83
|
-
sbf
|
|
82
|
+
# Скопировать существующего бота
|
|
83
|
+
sbf copy best-valera new-valera
|
|
84
|
+
|
|
84
85
|
```
|
|
85
86
|
|
|
87
|
+
**💡 Команда `copy` - создает нового бота на основе существующего:**
|
|
88
|
+
|
|
89
|
+
- ✅ Копирует код бота с автозаменой `bot_id`
|
|
90
|
+
- ✅ Копирует все промпты
|
|
91
|
+
- ✅ Копирует тесты и файлы
|
|
92
|
+
- ✅ Создает новый `.env` (не копирует токены)
|
|
93
|
+
|
|
86
94
|
### Управление ботами
|
|
87
95
|
|
|
88
96
|
```bash
|
|
@@ -235,7 +243,7 @@ async def handler(user_id: int, user_data: str):
|
|
|
235
243
|
|
|
236
244
|
**Формула времени с `event_type`:**
|
|
237
245
|
|
|
238
|
-
```
|
|
246
|
+
```text
|
|
239
247
|
reminder_time = event_datetime - delay
|
|
240
248
|
```
|
|
241
249
|
|
|
@@ -589,8 +597,8 @@ from smart_bot_factory.message import send_message
|
|
|
589
597
|
async def send_catalog(user_id: int, event_data: str):
|
|
590
598
|
"""Отправляет каталог с файлами"""
|
|
591
599
|
from smart_bot_factory.message import get_bot
|
|
592
|
-
|
|
593
|
-
|
|
600
|
+
from smart_bot_factory.supabase import SupabaseClient
|
|
601
|
+
|
|
594
602
|
bot = get_bot()
|
|
595
603
|
supabase_client = SupabaseClient("my-bot")
|
|
596
604
|
|
|
@@ -728,7 +736,7 @@ if __name__ == "__main__":
|
|
|
728
736
|
|
|
729
737
|
## 📖 Структура проекта
|
|
730
738
|
|
|
731
|
-
```
|
|
739
|
+
```text
|
|
732
740
|
project/
|
|
733
741
|
├── bots/
|
|
734
742
|
│ └── my-bot/
|
|
@@ -748,7 +756,7 @@ project/
|
|
|
748
756
|
|
|
749
757
|
## ⚙️ Конфигурация (.env)
|
|
750
758
|
|
|
751
|
-
```
|
|
759
|
+
```bash
|
|
752
760
|
# Telegram
|
|
753
761
|
TELEGRAM_BOT_TOKEN=your_token_here
|
|
754
762
|
|
|
@@ -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
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/integrations/openai_client.py
RENAMED
|
@@ -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,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "✨ Запрос функции"
|
|
3
|
-
about: Предложить новую функцию или улучшение
|
|
4
|
-
title: ''
|
|
5
|
-
labels: enhancement
|
|
6
|
-
assignees: ''
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 🎯 Описание функции
|
|
11
|
-
Что вы хотите добавить/улучшить?
|
|
12
|
-
|
|
13
|
-
## 💡 Мотивация
|
|
14
|
-
Какую проблему это решит?
|
|
15
|
-
|
|
16
|
-
## 📋 Детали реализации
|
|
17
|
-
Как вы видите это решение?
|
|
18
|
-
|
|
19
|
-
## 🔄 Альтернативы
|
|
20
|
-
Рассматривали ли другие варианты?
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "\U0001F41B Баг репорт"
|
|
3
|
-
about: Сообщить об ошибке
|
|
4
|
-
title: ''
|
|
5
|
-
labels: bug
|
|
6
|
-
assignees: ''
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 🐛 Описание проблемы
|
|
11
|
-
Опишите что пошло не так
|
|
12
|
-
|
|
13
|
-
## 🔄 Как воспроизвести
|
|
14
|
-
1. Пользователь написал...
|
|
15
|
-
2. Бот ответил...
|
|
16
|
-
3. Произошла ошибка...
|
|
17
|
-
|
|
18
|
-
## ✅ Ожидаемое поведение
|
|
19
|
-
Что должно было произойти
|
|
20
|
-
|
|
21
|
-
## 📱 Окружение
|
|
22
|
-
- **Bot ID:** (например, growthmed-october-24)
|
|
23
|
-
- **Время:** (когда произошло)
|
|
24
|
-
- **User ID:** (если известен)
|
|
25
|
-
|
|
26
|
-
## 📋 Логи
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ main ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
strategy:
|
|
13
|
-
matrix:
|
|
14
|
-
python-version: ["3.12", "3.13"]
|
|
15
|
-
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v4
|
|
18
|
-
|
|
19
|
-
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
-
uses: actions/setup-python@v5
|
|
21
|
-
with:
|
|
22
|
-
python-version: ${{ matrix.python-version }}
|
|
23
|
-
|
|
24
|
-
- name: Install dependencies
|
|
25
|
-
run: |
|
|
26
|
-
python -m pip install --upgrade pip
|
|
27
|
-
pip install -e .
|
|
28
|
-
|
|
29
|
-
- name: Run tests
|
|
30
|
-
run: |
|
|
31
|
-
pytest --cov=smart_bot_factory tests/
|
|
32
|
-
|
|
33
|
-
- name: Upload coverage to Codecov
|
|
34
|
-
uses: codecov/codecov-action@v4
|
|
35
|
-
with:
|
|
36
|
-
token: ${{ secrets.CODECOV_TOKEN }}
|
|
37
|
-
fail_ci_if_error: true
|
|
38
|
-
|
|
39
|
-
lint:
|
|
40
|
-
runs-on: ubuntu-latest
|
|
41
|
-
|
|
42
|
-
steps:
|
|
43
|
-
- uses: actions/checkout@v4
|
|
44
|
-
|
|
45
|
-
- name: Set up Python
|
|
46
|
-
uses: actions/setup-python@v5
|
|
47
|
-
with:
|
|
48
|
-
python-version: "3.12"
|
|
49
|
-
|
|
50
|
-
- name: Install dependencies
|
|
51
|
-
run: |
|
|
52
|
-
python -m pip install --upgrade pip
|
|
53
|
-
pip install flake8 black isort
|
|
54
|
-
|
|
55
|
-
- name: Check code style
|
|
56
|
-
run: |
|
|
57
|
-
flake8 src/smart_bot_factory tests
|
|
58
|
-
black --check src/smart_bot_factory tests
|
|
59
|
-
isort --check-only src/smart_bot_factory tests
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
name: Publish to GitHub Packages
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
permissions:
|
|
11
|
-
contents: read
|
|
12
|
-
packages: write
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v4
|
|
16
|
-
|
|
17
|
-
- name: Set up Python
|
|
18
|
-
uses: actions/setup-python@v4
|
|
19
|
-
with:
|
|
20
|
-
python-version: "3.9"
|
|
21
|
-
|
|
22
|
-
- name: Install build tools
|
|
23
|
-
run: |
|
|
24
|
-
python -m pip install --upgrade pip
|
|
25
|
-
pip install build twine
|
|
26
|
-
|
|
27
|
-
- name: Build package
|
|
28
|
-
run: python -m build
|
|
29
|
-
|
|
30
|
-
- name: Publish to GitHub Packages
|
|
31
|
-
env:
|
|
32
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
33
|
-
run: |
|
|
34
|
-
python -m twine upload --repository-url https://maven.pkg.github.com/${{ github.repository }} dist/*
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
name: Publish to PyPI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- uses: actions/checkout@v4
|
|
12
|
-
|
|
13
|
-
- name: Set up Python
|
|
14
|
-
uses: actions/setup-python@v4
|
|
15
|
-
with:
|
|
16
|
-
python-version: "3.9"
|
|
17
|
-
|
|
18
|
-
- name: Install build tools
|
|
19
|
-
run: |
|
|
20
|
-
python -m pip install --upgrade pip
|
|
21
|
-
pip install build twine
|
|
22
|
-
|
|
23
|
-
- name: Build package
|
|
24
|
-
run: python -m build
|
|
25
|
-
|
|
26
|
-
- name: Publish to PyPI
|
|
27
|
-
env:
|
|
28
|
-
TWINE_USERNAME: __token__
|
|
29
|
-
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
30
|
-
run: |
|
|
31
|
-
twine upload dist/*
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/1sales_context.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/2product_info.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/3objection_handling.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/final_instructions.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/help_message.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/prompts/welcome_message.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/quick_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/realistic_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/best-valera/tests/scenario_examples.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/3objection_handling.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/prompts/final_instructions.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/tests/realistic_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/tests/scenario_examples.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/bots/valera/welcome_files/welcome_file_msg.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_manager.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/admin_migration.sql
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/admin/timeout_checker.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/analytics/analytics_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/conversation_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/message_sender.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/core/router_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/creation/bot_builder.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/creation/bot_testing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/table/database_structure.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/debug_routing.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/prompt_loader.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.3.1 → smart_bot_factory-0.3.2}/smart_bot_factory/utils/user_prompt_loader.py
RENAMED
|
File without changes
|
|
File without changes
|