Files
ERP/bot/INTEGRATION-REPORT.md
T
whqreza 638076dbaa refactor(bot)!: rename 'ai procurement' -> 'bot/' so the compose build context is committed
The bot service in docker-compose.yml builds from ./bot, but the agent code lived in 'ai procurement/' and ./bot was only a Windows junction on reza.g's machine (and was gitignored) — exactly as the team reported: 'bot/ was never committed — prod-v7's bot is un-buildable from the repo.'

- junction removed; 'ai procurement/' renamed to 'bot/' via git mv (all 41 files keep their history as pure renames)
- 'bot/' dropped from .gitignore (voice/ stays ignored — runtime voice notes; bot/.env stays ignored by bot/.gitignore)
- compose needs no change: context: ./bot and ./bot/app now resolve to committed files
- bot/INTEGRATION-REPORT.md added: full story (problem, root cause, git state, security note on the committed BALE_BOT_TOKEN / AI_API_KEY compose defaults, and usage instructions for the team)

Verified: 41 renames staged with zero secret/cache files; voice/ and bot/.env still ignored.
2026-10-02 12:52:25 +03:30

151 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# گزارش ادغام ایجنت هوش مصنوعی با ریپوی ERP
> این سند وضعیت نهایی یکپارچه‌سازی بات تلگرام/بله (procurement AI agent) با پروژه‌ی ERP را
> توضیح می‌دهد: مشکلی که پیش آمده بود، چه چیزی اصلاح شد، وضعیت فعلی گیت و سرور،
> نکات امنیتی و نحوه‌ی استفاده. تاریخ آخرین به‌روزرسانی: برنچ `prod-v7`.
---
## ۱. مشکل چی بود؟
سرویس `bot` در `docker-compose.yml` این‌طور تعریف شده بود:
```yaml
bot:
build:
context: ./bot # ← پوشه‌ای که در گیت وجود نداشت!
volumes:
- ./bot/app:/srv/bot/app
```
اما:
1. **پوشه‌ی `bot/` هیچ‌وقت کامیت نشده بود** — نه روی `prod-v7` و نه روی هیچ برنچ دیگری.
2. کد ایجنت در پوشه‌ای به نام `ai procurement/` (با فاصله در نام) زندگی می‌کرد که روی `prod-v7` کامیت شده بود، ولی compose به آن اشاره نمی‌کرد.
3. روی دستگاه reza.g یک **Windows Junction** (میان‌بر سطح NTFS) به نام `bot` وجود داشت که به `ai procurement` اشاره می‌کرد — به همین دلیل `docker compose build bot` فقط روی ماشین او جواب می‌داد.
4. خود برنچ `prod-v7` هم `bot/` را در `.gitignore` (خط ۳۳) داشت.
**نتیجه:** روی هر کلون تمیزی از مخزن، `docker compose build bot` شکست می‌خورد —
همان چیزی که تیم گزارش کرد: «bot/ was never committed — prod-v7's bot is un-buildable from the repo.»
## ۲. راه‌حل اعمال‌شده (راه‌حل شماره ۲)
1. Junction ویندوزی `bot` حذف شد (فقط میان‌بر؛ فایلی از دست نرفت).
2. پوشه‌ی `ai procurement/` به **`bot/`** تغییر نام یافت — با `git mv`، یعنی
**تاریخچه‌ی گیت هر ۴۱ فایل به‌صورت rename خالص حفظ شده** (`R` در گیت، نه حذف/افزودن).
3. خط `bot/` از `.gitignore` ریشه حذف شد تا پوشه‌ی بات دیگر ignore نشود.
(`voice/` سر جایش ماند — نت‌های صوتی رuntimes هستند و نباید کامیت شوند.)
4. اکنون `docker-compose.yml` **بدون هیچ تغییری** درست کار می‌کند:
`context: ./bot` و `./bot/app` دقیقاً به فایل‌های کامیت‌شده اشاره می‌کنند.
5. همه‌چیز روی برنچ **`prod-v7`** کامیت و پوش شده تا تیم به فایل‌ها دسترسی داشته باشد.
### قواعد ignore فعلی (عمدی)
| مسیر | وضعیت | دلیل |
|---|---|---|
| `bot/.env` | ignore (توسط `bot/.gitignore`) | کلیدها و توکن‌ها — هرگز کامیت نمی‌شوند |
| `bot/__pycache__/` و `*.pyc` | ignore | خروجی runtime پایتون |
| `voice/` | ignore (ریشه) | فایل‌های صوتی دریافتی از بله در زمان اجرا |
| `procurement_ai_agent.bundle` و `git_history_backup.zip` | **کامیت‌شده** | بکاپ تاریخچه‌ی اصلی ایجنت (~۲۰۰KB) |
## ۳. وضعیت فعلی گیت (تاریخ این سند)
- برنچ فعال: **`prod-v7`** (محلی و `origin/prod-v7` هم‌SHA).
- درخت `prod-v7` = کل اپلیکیشن ERP (backend/frontend/…) **به‌علاوه‌ی** `bot/`
(کد ایجنت + Dockerfile + docs + integration) + `backend/app/routers/drafts.py`
(اندپوینت‌های همگام‌سازی draft بات ↔ ویزارد) + اسکیمای `bot_drafts`.
- تاریخچه: از production (d69ec7f) یازده کامیت جلوتر — از «feat(drafts): bot_drafts schema»
تا «feat(bot,wizard): smart message filtering…».
- بقیه‌ی برنچ‌های تیم (`prod-v8`، `prod-v9`، `prod_v8`، `production`) **فایل‌های بات را ندارند** —
ادغام این برنچ با کار جدید تیم، قدم بعدی جداگانه است (با تأیید تیم).
## ۴. ⚠️ نکته‌ی امنیتی (مهم — اقدام لازم)
در همان `docker-compose.yml`، مقادیر **واقعی** به‌عنوان پیش‌فرض env کامیت و پوش شده‌اند:
```yaml
PROCUREMENT_BOT_BOT_TOKEN: ${BALE_BOT_TOKEN:-1354444845:yhVMnKZBFuKaU3UW5fP1bHmknEHx99mipWw}
PROCUREMENT_BOT_AI_API_KEY: ${AI_API_KEY:-sk-a671eab15be846d494bf0839070a3b32}
```
یعنی توکن بات بله و کلید DeepSeek الان در تاریخچه‌ی مخزن مشترک است و **هر کسی که به ریپو
دسترسی دارد می‌تواند آن‌ها را ببیند** (`.env` کامیت نشده، ولی این پیش‌فرض‌ها عملاً همان لو رفتن راز است).
اقدامات توصیه‌شده (هنوز انجام نشده — نیاز به تصمیم مالک توکن‌ها):
1. **توکن بات بله را از @BotFather بله باطل و دوباره بسازید** و کلید DeepSeek را rotate کنید.
2. مقادیر پیش‌فرض را از compose حذف کنید و به‌جای `${VAR:-secret}` از `${VAR:?set VAR}` استفاده کنید
(مثل `TRAEFIK_ACME_EMAIL` در compose پروडاکشن) و مقادیر واقعی فقط در `.env` محلی/سرور بمانند.
3. فایل `bot/.env` را از روی `bot/.env.example` بسازید (نمونه در همان پوشه هست).
## ۵. نحوه‌ی استفاده
### ۵.۱ اجرای کامل استک (شامل بات) — روی هر ماشین
```powershell
git clone https://git.bennu-api-bahrestan.ir/ali_mohaghegh/ERP.git
cd ERP
git checkout prod-v7
# ۱) متغیرهای محیطی بات را بسازید (بدون این، بات توکن ندارد):
copy bot\.env.example bot\.env # و مقادیر واقعی را داخلش بگذارید
# BALE_BOT_TOKEN=... توکن بات از بله
# AI_API_KEY=... کلید سرویس LLM
# BALE_ADMIN_CHAT_IDS=... چت‌آیدی مدیران
# ۲) کل استک + بات:
docker compose up -d --build
```
سرویس `bot` (کانتینر `procurement-bot`) به‌صورت long-polling به `tapi.bale.ai` وصل می‌شود،
به `api:8000/api/v1` (همان ERP) و پایگاه‌داده‌ی `procurement` وصل است و
draft های گفتگو را در جدول `bot_drafts` می‌نویسد.
### ۵.۲ اجرای فقط بات (وقتی استک از قبل بالا است)
```powershell
docker compose build bot
docker compose up -d bot
docker compose logs -f bot
```
### ۵.۳ جریان کاری کاربر نهایی (بات ↔ ERP)
1. کاربر در بله به بات پیام می‌دهد (متن یا وویس — وویس با STT به متن تبدیل می‌شود).
2. بات با NLU موجودی/تأمین‌کننده/کالا را استخراج می‌کند و یک **draft** می‌سازد
(وضعیت `active` در جدول `bot_drafts`) و کارت پیش‌نمایش با فیلدهای خالی می‌فرستد.
3. کاربر با دکمه‌ی ✅ تأیید می‌کند؛ بات draft را به ERP کامیت می‌کند
(از طریق REST: `POST /api/v1/drafts/{id}/commit` با توکن سرویس).
4. ویزارد فرانت‌اند همان draft را از `GET /api/v1/drafts` می‌خواند و پیش‌پر می‌کند —
همگام‌سازی دوطرفه با ذخیره‌ی خودکار (debounced) بین مرورگر و بات.
5. ویرایشِ پاسخِ کاربر به کارت قبلی بات هم پشتیبانی می‌شود (reply-based edit، بدون کارت تکراری).
### ۵.۴ تست سریع سلامت
```powershell
docker compose ps bot # باید Up باشد
docker compose logs bot | Select-Object -Last 20
# داخل کانتینر:
docker compose exec bot python -m tools.smoke_test # اگر توکن ست باشد
```
### ۵.۵ مسیرهای مهم
| مسیر | محتوا |
|---|---|
| `bot/app/` | کد بات (handlers برای quote/material/supplier/decisions، bale client، NLU، STT، sync) |
| `bot/Dockerfile` | ایمیج `python:3.13-slim` + ffmpeg (برای وویس) |
| `bot/docs/SETUP.md` | راه‌اندازی جزئی‌تر ایجنت |
| `bot/integration/` | طرح ادغام: نمونه سرویس compose + پچ `X-Actor-Id` |
| `backend/app/routers/drafts.py` | REST drafts (سمت ERP) |
| `bot/procurement_ai_agent.bundle` و `bot/git_history_backup.zip` | بکاپ تاریخچه‌ی مستقل قبلی ایجنت |
## ۶. نکات باقی‌مانده برای تیم
- **ادغام با برنچ‌های جدید تیم:** فایل‌های بات فقط روی `prod-v7` هستند؛ `prod-v8`/`prod-v9`
آن‌ها را ندارند. برای رسیدن به استقرار نهایی، این برنچ باید با کار تیم merge شود.
- **سرویس bot در `docker-compose.prod.yml` و `docker-compose.coolify.yml` نیست** —
برای استقرار سرور باید به overlay پروڈ اضافه شود (یا از همان base compose استفاده شود).
- نام قدیمی `ai procurement` در برخی مستندات (`bot/docs/SETUP.md`، `bot/integration/`)
ممکن است هنوز دیده شود — محتوایی است و عملکردی تحت تأثیر نیست.