معماری
پشته و چیدمان
Pitchbar یک کدبیس لاراول با دو فرانتاند است. بکاند لاراول ۱۳ بههمراه Octane روی PHP 8.3+ است؛ رابط مدیریتی اینرسی v3 + React 19 است و ویجت بازدیدکننده Preact با حجم ≤۵۰ کیلوبایت. پشتهی هوش مصنوعی بهطور پیشفرض از کلودفلر (Workers AI + Vectorize + Browser Rendering) با OpenAI و Qdrant بهعنوان پشتیبان استفاده میکند.
پشته فناوری
| لایه | فناوری |
|---|---|
| چارچوب برنامه | Laravel 13 (PHP 8.3+) |
| سرور | Laravel Octane روی FrankenPHP |
| بیدرنگ | Laravel Reverb (WebSocket) |
| صف | Laravel Horizon روی Redis |
| احراز هویت | Laravel Fortify (نشستها، احراز هویت دو مرحلهای، بازنشانی رمز عبور) + Sanctum (توکنهای API) |
| صورتحساب | Laravel Cashier (Stripe) |
| پایگاه داده | Postgres 16 |
| کش / نشستها | Redis 7 |
| فرانتاند مدیریت | Inertia v3 + React 19، Tailwind v4، shadcn/ui (Radix)، Vite، TypeScript سختگیرانه |
| مسیرهای نوعدار | Wayfinder (اتصال TypeScript به مسیرهای لاراول) |
| ویجت بازدیدکننده | Preact 10 (با نام مستعار React) + Vite + Tailwind v4 انتخابی |
| هوش مصنوعی (ترجیح) | Cloudflare Workers AI — Llama 3.3 70B + bge-base-en-v1.5 |
| هوش مصنوعی (پشتیبان) | OpenAI gpt-4o-mini + text-embedding-3-small (و OpenRouter بهعنوان مسیریاب) |
| ذخیرهساز جستجوی هوشمند (ترجیح) | Cloudflare Vectorize |
| ذخیرهساز جستجوی هوشمند (پشتیبان) | Qdrant (مشتری HTTP) |
| خزنده (ترجیح) | Cloudflare Browser Rendering |
| خزنده (پشتیبان) | Browserless → HTTP ساده |
| ذخیرهسازی اشیاء | Cloudflare R2 (سازگار با S3) |
| میزبانی | Laravel Cloud |
| قابلیت مشاهده | Sentry + OpenTelemetry → Honeycomb / Grafana Cloud |
ساختار مخزن
یک برنامه لاراول در ریشه مخزن. فرانتاند مدیریت بهعنوان صفحات اینرسی در همان برنامه ارائه میشود؛ ویجت بازدیدکننده یک ساخت Vite مجزا و ایزوله است.
pitchbar/ — برنامه لاراول
├── app/
│ ├── Actions/Fortify/ — قلابهای Fortify (CreateNewUser و غیره)
│ ├── Concerns/ — ویژگیهای BelongsToWorkspace، BelongsToAgent
│ ├── Http/
│ │ ├── Controllers/Admin/ — کنترلرهای اینرسی مشتری + مدیریت
│ │ ├── Controllers/Widget/ — /api/v1/widget/* (سمت بازدیدکننده، JWT)
│ │ └── Middleware/
│ ├── Models/ — Workspace, Agent, Conversation, Plan, …
│ ├── Services/
│ │ ├── Rag/ — بازیابی، تکهتکهکننده، ساخت راهنما، تطابق پاسخ گزینشی
│ │ ├── Llm/ — OpenAiHttpClient، WorkersAiClient، Fakes
│ │ ├── Vector/ — VectorizeClient، QdrantHttpClient
│ │ ├── Crawl/ — CloudflareBrowserClient، AutoIndexPageVisit، PlainHttpCrawler
│ │ ├── Triggers/ — انتخابگر فراخوان، تشخیص قصد مشتری
│ │ ├── Analytics/ — ذخیرهساز رویداد (تجمیع تحلیلها و تشخیص شکاف در app/Jobs/Analytics)
│ │ ├── Billing/ — همگامسازی محصول Stripe، صورتحساب سنجشی، PayPalClient، RazorpayClient
│ │ ├── Tools/ — ثبت ابزار + ابزار ارجاع به انسان (فاز ۲)
│ │ ├── Vertical/ — ثبت پیشتنظیم عمودی + ۷ کلاس پیشتنظیم
│ │ ├── I18n/ — تشخیص محلی، کاتالوگ محلی (۱۳۲ زبان)
│ │ └── Widget/ — WidgetJwt، WidgetCopy، تجزیهکننده بلوک درونخطی
│ ├── Jobs/Crawl/ — CrawlSourceJob، CrawlPageJob، IndexDocumentJob
│ ├── Jobs/Analytics/ — DetectGapJob (تشخیص شکاف پس از جریان)
│ └── Events/ — TokenStreamed، TurnCompleted، TurnFailed
├── resources/
│ ├── js/ — مدیریت اینرسی (ساخت Vite پیشفرض)
│ │ ├── pages/
│ │ ├── components/
│ │ └── …
│ ├── widget/ — ویجت بازدیدکننده (ساخت Vite جداگانه)
│ ├── views/ — Blade (ریشه اینرسی + بازاریابی + مستندات)
│ └── css/app.css — ورودی Tailwind v4
├── routes/
│ ├── web.php
│ ├── api.php
│ └── channels.php
├── database/{migrations,factories,seeders}
├── tests/{Feature,Unit,Browser}
├── docs/PLAN.md — برنامه کامل مهندسی
└── public/widget/ — بسته ویجت ساختهشده
دو فرانتاند، یک بکاند
سطوح مدیریت و مشتری، همان برنامه اینرسی هستند — همان ساخت Vite، همان کتابخانه کامپوننت. نقشها توسط گروه مسیر و میانافزار جدا میشوند، نه توسط کدبیس. این کار یک منبع واحد برای نشانههای طراحی، کمکهای مسیریابی و وضعیت احراز هویت حفظ میکند.
ویجت بازدیدکننده برعکس است — عمداً هیچ چیزی با کد مدیریت به اشتراک نمیگذارد. نمیتواند از resources/js/ وارد کند؛ پیکربندی Vite مخصوص خود را دارد؛ مسیریاب مخصوص خود (فقط یک درخت کامپوننت Preact) و وضعیت مخصوص خود را دارد. محدودیت حجم، سختافزاری ۵۰ کیلوبایت gzip است — قابلیتهای مدیریت نمیتوانند به آن نفوذ کنند.
Reverb و WebSocket
Reverb بهعنوان یک فرآیند جداگانه اجرا میشود و موارد زیر را پشتیبانی میکند:
- بروزرسانیهای زنده صندوق ورودی — اپراتورها پیامهای جدید را به محض رسیدن میبینند.
- رویدادهای تحویل انسانی — وقتی اپراتور مکالمه را تصاحب میکند، ویجت بازدیدکننده رویداد «کارشناس در ارتباط است» را دریافت میکند.
- حضور اپراتور — وضعیت آنلاین / آفلاین در بین اعضای تیم همگامسازی میشود.
کانالها بهطور پیشفرض خصوصی هستند — ویجت با استفاده از JWT خود به conversation.{id} ملحق میشود و برنامه اپراتور با استفاده از نشست خود به workspace.{id} میپیوندد.
حالت یکقبض کلودفلر
CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN را تنظیم کنید و هوش مصنوعی، ذخیرهساز جستجوی هوشمند و خزنده همگی بهطور خودکار به کلودفلر متصل میشوند. هزینه کل زیرساخت خارجی: ۵ دلار در ماه Workers Paid + هزینه استفاده بهازای هر درخواست. هر بخش را جایگزین کنید (مثلاً با تنظیم QDRANT_URL Vectorize را با Qdrant عوض کنید) و اتصال تغییر میکند.
ایزولهسازی فضاهای کاری
هر پرسوجوی محدود به فضای کاری، توسط محدوده سراسری ویژگی BelongsToWorkspace فیلتر میشود. عبور از مرز نیاز به withoutWorkspaceScope() صریح با یک کامنت توجیهی دارد. یک تست بازگشتی وجود دارد که اگر مدلی با ستون workspace_id از این ویژگی استفاده نکند، ساخت را با شکست مواجه میکند. مشاهده کنید فضاهای کاری.