mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-18 15:29:36 +00:00
chore(dealix): launch runbooks, staging env templates, SQLite init on startup, product journey test
Co-authored-by: VoXc2 <VoXc2@users.noreply.github.com>
This commit is contained in:
parent
8c3d91c070
commit
69f5082e5e
36
salesflow-saas/.env.staging.example
Normal file
36
salesflow-saas/.env.staging.example
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Staging template — copy to `.env` on the staging host (never commit `.env`).
|
||||||
|
# Full variable list: `.env.example`. Phase-2 integrations checklist: `docs/INTEGRATION_MASTER_AR.md`
|
||||||
|
# and `backend/.env.phase2.example`.
|
||||||
|
|
||||||
|
ENVIRONMENT=staging
|
||||||
|
DEFAULT_TIMEZONE=Asia/Riyadh
|
||||||
|
|
||||||
|
# Docker Compose: keep @db / @redis hostnames. Bare metal: use 127.0.0.1 and matching ports.
|
||||||
|
DB_NAME=salesflow
|
||||||
|
DB_USER=salesflow
|
||||||
|
DB_PASSWORD=REPLACE_ME_STRONG
|
||||||
|
DATABASE_URL=postgresql+asyncpg://salesflow:REPLACE_ME_STRONG@db:5432/salesflow
|
||||||
|
|
||||||
|
REDIS_URL=redis://redis:6379/0
|
||||||
|
|
||||||
|
SECRET_KEY=REPLACE_ME_RANDOM_32PLUS_CHARS
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||||
|
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||||
|
|
||||||
|
# Public URLs for your staging domain (CORS + webhooks)
|
||||||
|
API_URL=https://api-staging.example.com
|
||||||
|
FRONTEND_URL=https://app-staging.example.com
|
||||||
|
NEXT_PUBLIC_API_URL=https://api-staging.example.com
|
||||||
|
WEBHOOK_BASE_URL=https://api-staging.example.com/api/v1/webhooks
|
||||||
|
|
||||||
|
# LLM — set at least one real key for AI features in staging
|
||||||
|
OPENAI_API_KEY=
|
||||||
|
GROQ_API_KEY=
|
||||||
|
|
||||||
|
# Channels — fill only what you will smoke-test (see launch checklist)
|
||||||
|
WHATSAPP_API_TOKEN=
|
||||||
|
WHATSAPP_PHONE_NUMBER_ID=
|
||||||
|
WHATSAPP_VERIFY_TOKEN=
|
||||||
|
|
||||||
|
SMTP_USER=
|
||||||
|
SMTP_PASSWORD=
|
||||||
@ -28,10 +28,12 @@ Frontend: `http://localhost:3000`
|
|||||||
|
|
||||||
**If the browser shows connection refused on `:3000` or `:8000`:** nothing is listening on that port yet. Start the stack (`docker compose up` from this folder) or run `uvicorn` / `npm run dev` manually. Confirm with `curl -sSf http://127.0.0.1:8000/api/v1/health` and ensure the browser is on the same machine as the server (not WSL/remote without port forwarding).
|
**If the browser shows connection refused on `:3000` or `:8000`:** nothing is listening on that port yet. Start the stack (`docker compose up` from this folder) or run `uvicorn` / `npm run dev` manually. Confirm with `curl -sSf http://127.0.0.1:8000/api/v1/health` and ensure the browser is on the same machine as the server (not WSL/remote without port forwarding).
|
||||||
|
|
||||||
**Without Docker:** install Python 3.12+ and Node 22+, copy `.env` and `frontend/.env.local`, run Postgres/Redis (or point `DATABASE_URL` / `REDIS_URL` at existing instances), then `cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000` and `cd frontend && npm run dev`.
|
**Without Docker:** install Python 3.12+ and Node 22+, copy `.env` and `frontend/.env.local`, run Postgres/Redis (or point `DATABASE_URL` / `REDIS_URL` at existing instances), then `cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000` and `cd frontend && npm run dev`. If `DATABASE_URL` uses SQLite (`sqlite+aiosqlite`), the API runs `init_db()` on startup so tables exist for local smoke tests; production should use Postgres + Alembic migrations.
|
||||||
|
|
||||||
**E2E locally:** after `npm ci`, run `npx playwright install chromium` once, then `npm run test:e2e` (matches CI).
|
**E2E locally:** after `npm ci`, run `npx playwright install chromium` once, then `npm run test:e2e` (matches CI).
|
||||||
|
|
||||||
|
**Staging env templates:** `.env.staging.example` (repo root) and `frontend/.env.staging.example` — copy to `.env` / `frontend/.env.local` on the host; see `docs/STAGING_ENV_CHECKLIST.md`.
|
||||||
|
|
||||||
**Customer onboarding (B2B):** `GET /api/v1/customer-onboarding/journey` and `docs/CUSTOMER_OS_ONBOARDING_AR.md`. Dashboard tab: **مسار التشغيل مع العميل**.
|
**Customer onboarding (B2B):** `GET /api/v1/customer-onboarding/journey` and `docs/CUSTOMER_OS_ONBOARDING_AR.md`. Dashboard tab: **مسار التشغيل مع العميل**.
|
||||||
|
|
||||||
**Launch verification:** see `docs/LAUNCH_CHECKLIST.md`. From `salesflow-saas`: copy `frontend/.env.example` to `frontend/.env.local` and set `NEXT_PUBLIC_API_URL`. Run `.\verify-launch.ps1 -HttpCheck -SoftReady` (use `-BaseUrl` if the API is not on port 8000).
|
**Launch verification:** see `docs/LAUNCH_CHECKLIST.md`. From `salesflow-saas`: copy `frontend/.env.example` to `frontend/.env.local` and set `NEXT_PUBLIC_API_URL`. Run `.\verify-launch.ps1 -HttpCheck -SoftReady` (use `-BaseUrl` if the API is not on port 8000).
|
||||||
|
|||||||
@ -61,6 +61,8 @@ async def get_db():
|
|||||||
|
|
||||||
|
|
||||||
async def init_db():
|
async def init_db():
|
||||||
|
import app.models # noqa: F401 — register all models on Base.metadata before create_all
|
||||||
|
|
||||||
async with engine.begin() as conn:
|
async with engine.begin() as conn:
|
||||||
if not IS_SQLITE:
|
if not IS_SQLITE:
|
||||||
for ext in ["CREATE EXTENSION IF NOT EXISTS vector",
|
for ext in ["CREATE EXTENSION IF NOT EXISTS vector",
|
||||||
|
|||||||
@ -12,6 +12,7 @@ from contextlib import asynccontextmanager
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from app.config import get_settings
|
from app.config import get_settings
|
||||||
|
from app.database import IS_SQLITE, init_db
|
||||||
from app.api.v1.router import api_router
|
from app.api.v1.router import api_router
|
||||||
from app.flows.self_improvement_flow import self_improvement_flow
|
from app.flows.self_improvement_flow import self_improvement_flow
|
||||||
from app.middleware.internal_api import InternalApiTokenMiddleware
|
from app.middleware.internal_api import InternalApiTokenMiddleware
|
||||||
@ -70,6 +71,8 @@ async def lifespan(app: FastAPI):
|
|||||||
print(f" Environment: {settings.ENVIRONMENT}")
|
print(f" Environment: {settings.ENVIRONMENT}")
|
||||||
print(f" LLM Primary: {settings.LLM_PRIMARY_PROVIDER}")
|
print(f" LLM Primary: {settings.LLM_PRIMARY_PROVIDER}")
|
||||||
print(f" LLM Fallback: {settings.LLM_FALLBACK_PROVIDER}")
|
print(f" LLM Fallback: {settings.LLM_FALLBACK_PROVIDER}")
|
||||||
|
if IS_SQLITE:
|
||||||
|
await init_db()
|
||||||
yield
|
yield
|
||||||
# Shutdown
|
# Shutdown
|
||||||
stop_event.set()
|
stop_event.set()
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
"""
|
||||||
|
Staging / CI — مسار منتج واحد + دخان قناة (بريد عبر outreach بدون إرسال SMTP).
|
||||||
|
|
||||||
|
يُكمّل test_new_subscriber_journey ويُثبت أن القنوات تستجيب بعد تسجيل مستخدم.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from httpx import ASGITransport, AsyncClient
|
||||||
|
|
||||||
|
from app.main import app
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.launch
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_staging_happy_path_dashboard_and_email_channel_draft():
|
||||||
|
suffix = uuid.uuid4().hex[:14]
|
||||||
|
email = f"staging_path_{suffix}@dealix.journey.test"
|
||||||
|
password = "Staging_Secure_Pass_9"
|
||||||
|
|
||||||
|
transport = ASGITransport(app=app)
|
||||||
|
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
||||||
|
reg = await ac.post(
|
||||||
|
"/api/v1/auth/register",
|
||||||
|
json={
|
||||||
|
"company_name": f"Staging Path Co {suffix}",
|
||||||
|
"company_name_ar": "شركة مسار الاختبار",
|
||||||
|
"full_name": "مالك الاختبار",
|
||||||
|
"email": email,
|
||||||
|
"password": password,
|
||||||
|
"phone": "0501112233",
|
||||||
|
"industry": "real_estate",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert reg.status_code == 200, reg.text
|
||||||
|
token = reg.json()["access_token"]
|
||||||
|
|
||||||
|
dash = await ac.get(
|
||||||
|
"/api/v1/dashboard/overview",
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
)
|
||||||
|
assert dash.status_code == 200
|
||||||
|
|
||||||
|
outreach = await ac.post(
|
||||||
|
"/api/v1/outreach",
|
||||||
|
json={
|
||||||
|
"channel": "email",
|
||||||
|
"lead": {
|
||||||
|
"name": "عميل تجريبي",
|
||||||
|
"company": "عقار الرياض",
|
||||||
|
"sector": "عقار",
|
||||||
|
},
|
||||||
|
"campaign_type": "cold_intro",
|
||||||
|
"language": "ar",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert outreach.status_code == 200, outreach.text
|
||||||
|
body = outreach.json()
|
||||||
|
assert body.get("channel") == "email"
|
||||||
|
assert "subject" in body and "body" in body
|
||||||
|
assert len(body["subject"]) > 0 and len(body["body"]) > 0
|
||||||
40
salesflow-saas/docs/DOCKER_FULL_STACK.md
Normal file
40
salesflow-saas/docs/DOCKER_FULL_STACK.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Dealix — تشغيل الستاك الكامل بـ Docker Compose
|
||||||
|
|
||||||
|
من مجلد `salesflow-saas`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# عدّل .env (SECRET_KEY، كلمات مرور DB، مفاتيح اختيارية)
|
||||||
|
|
||||||
|
docker compose up -d --build
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## قاعدة البيانات والبذور
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make migrate
|
||||||
|
make seed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Celery
|
||||||
|
|
||||||
|
الخدمات: `celery_worker`, `celery_beat`. للتحقق:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose logs -f celery_worker --tail=50
|
||||||
|
```
|
||||||
|
|
||||||
|
إذا كانت الميزات (تسلسلات، مهام مجدولة) لا تعمل، راجع أن Redis و`REDIS_URL` سليمة وأن الـ worker يعمل دون أخطاء متكررة.
|
||||||
|
|
||||||
|
## إيقاف التشغيل
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
# مع حذف الحجم (احذر — يمسح بيانات Postgres المحلية):
|
||||||
|
# docker compose down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## بيئة بدون Docker
|
||||||
|
|
||||||
|
على أجهزة التطوير التي لا تتوفر فيها Docker، استخدم نفس أوامر CI: `pytest` مع SQLite و`npm run build`، وتشغيل `uvicorn` محلياً مع Postgres/Redis منفصلين أو قاعدة SQLite للاختبارات فقط — لا يغني ذلك عن اختبار staging حقيقي قبل الإنتاج.
|
||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
- [ ] تشغيل من **أحدث** كود في المستودع:
|
- [ ] تشغيل من **أحدث** كود في المستودع:
|
||||||
`cd backend && py -m uvicorn app.main:app --host 0.0.0.0 --port 8000`
|
`cd backend && py -m uvicorn app.main:app --host 0.0.0.0 --port 8000`
|
||||||
|
- [ ] **SQLite محلي فقط:** عند `DATABASE_URL=sqlite+aiosqlite://...` يُنشئ التطبيق الجداول عند الإقلاع (`init_db`) لتسهيل الاختبار؛ **الإنتاج يستخدم Postgres + Alembic** (`make migrate`) وليس الاعتماد على `create_all`.
|
||||||
- [ ] إذا ظهر **404** على `/api/v1/marketing/hub` أو `/api/v1/strategy/summary` فالعملية غالباً **قديمة** — أعد تشغيل `uvicorn` بعد `git pull`.
|
- [ ] إذا ظهر **404** على `/api/v1/marketing/hub` أو `/api/v1/strategy/summary` فالعملية غالباً **قديمة** — أعد تشغيل `uvicorn` بعد `git pull`.
|
||||||
- [ ] اختبار HTTP:
|
- [ ] اختبار HTTP:
|
||||||
`py scripts/full_stack_launch_test.py --http-only --soft-ready`
|
`py scripts/full_stack_launch_test.py --http-only --soft-ready`
|
||||||
@ -31,6 +32,11 @@
|
|||||||
|
|
||||||
- [ ] مراقبة `/api/v1/health` و `/api/v1/ready`.
|
- [ ] مراقبة `/api/v1/health` و `/api/v1/ready`.
|
||||||
- [ ] مراجعة `go-live-gate` عند التكاملات الحقيقية (قد يعيد 403 حتى اكتمال التهيئة — متوقع).
|
- [ ] مراجعة `go-live-gate` عند التكاملات الحقيقية (قد يعيد 403 حتى اكتمال التهيئة — متوقع).
|
||||||
|
- [ ] خطة التراجع والقطع: `memory/runbooks/ROLLBACK_AND_GO_LIVE.md`.
|
||||||
|
|
||||||
|
## 6. تمييز السوق (قبل الإعلان)
|
||||||
|
|
||||||
|
- [ ] مراجعة `docs/MARKET_POSITIONING_AR.md` ومواءمة النسخ مع الميزات المفعّلة فعلياً.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
25
salesflow-saas/docs/MARKET_POSITIONING_AR.md
Normal file
25
salesflow-saas/docs/MARKET_POSITIONING_AR.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Dealix — تمييز السوق والرسالة (عربي)
|
||||||
|
|
||||||
|
## قصة قطاع: عقار في الرياض
|
||||||
|
|
||||||
|
**المشكلة:** فرق المبيعات تتلقى استفسارات من واتساب والموقع، لكن المتابعة غير موحّدة، والتأهيل يدوي، والامتثال لموافقات العملاء (PDPL) غير موثّق.
|
||||||
|
|
||||||
|
**الحل مع Dealix:** مسار واحد من Lead → تأهيل بالذكاء الاصطناعي (عربي) → تسلسل رسائل بحكم PDPL → لوحة للصفقات والموافقات. العملاء يرون **وقت أقل على التتبع** و**زيادة وضوح Pipeline**.
|
||||||
|
|
||||||
|
## مقارنة سريعة مع CRM عام (HubSpot-style)
|
||||||
|
|
||||||
|
| البعد | CRM عام | Dealix |
|
||||||
|
|--------|---------|--------|
|
||||||
|
| العربية والـ RTL | غالباً إضافة | أولاً في الواجهة والقوالب |
|
||||||
|
| واتساب كقناة أولى | يحتاج تكاملات وإعداد طويل | مسارات وقنوات مدمجة في المنتج (انظر التكاملات في `docs/INTEGRATION_MASTER_AR.md`) |
|
||||||
|
| PDPL والموافقات | مسؤولية العميل غالباً | طبقة خدمات ووثائق موجهة للسوق السعودي |
|
||||||
|
| «يوم واحد» | استيراد جهات اتصال | تشغيل سريع مع قوائم التحقق والـ staging templates |
|
||||||
|
|
||||||
|
## الامتثال كميزة
|
||||||
|
|
||||||
|
- التحقق من الموافقة قبل أي إرسال صادر مذكور في سياسة المنتج (`services/pdpl`).
|
||||||
|
- للمواد الخارجية: اذكر **PDPL** و**تسجيل الموافقات** بلغة عملاء الأعمال، دون وعود بميزات غير مفعّلة في البيئة التي تنشرونها.
|
||||||
|
|
||||||
|
## مواءمة النسخ مع المنتج الحي
|
||||||
|
|
||||||
|
قبل الحملات: راجع المسارات العامة (`/`، `/marketers`، `/strategy`) و`GET /api/v1/value-proposition/` و`GET /api/v1/customer-onboarding/journey` وتأكد أن الوعود في التسويق تطابق ما هو مُفعّل في الإنتاج.
|
||||||
26
salesflow-saas/docs/STAGING_ENV_CHECKLIST.md
Normal file
26
salesflow-saas/docs/STAGING_ENV_CHECKLIST.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Dealix — قائمة تهيئة بيئة Staging
|
||||||
|
|
||||||
|
استخدم هذا الملف مع [LAUNCH_CHECKLIST.md](LAUNCH_CHECKLIST.md) و [INTEGRATION_MASTER_AR.md](INTEGRATION_MASTER_AR.md).
|
||||||
|
|
||||||
|
## 1) ملفات البيئة
|
||||||
|
|
||||||
|
| الملف | الإجراء |
|
||||||
|
|--------|---------|
|
||||||
|
| جذر `salesflow-saas` | انسخ [`.env.staging.example`](../.env.staging.example) إلى `.env` واستبدل القيم |
|
||||||
|
| `frontend/` | انسخ [`frontend/.env.staging.example`](../frontend/.env.staging.example) إلى `frontend/.env.local` |
|
||||||
|
| تكاملات موسعة | راجع `backend/.env.phase2.example` واملأ الأقسام التي ستفعّلها فقط |
|
||||||
|
|
||||||
|
## 2) CORS
|
||||||
|
|
||||||
|
- `FRONTEND_URL` في `.env` يجب أن يطابق أصل الواجهة (مثلاً `https://app-staging.example.com`).
|
||||||
|
- إن تغيّر النطاق، حدّث إعدادات CORS في الباكند إن لزم.
|
||||||
|
|
||||||
|
## 3) بعد التشغيل
|
||||||
|
|
||||||
|
- `GET /api/v1/health` و `GET /api/v1/ready`
|
||||||
|
- سكربت اختياري: `python scripts/full_stack_launch_test.py --http-only --soft-ready` مع `DEALIX_BASE_URL`
|
||||||
|
- جولة يدوية سريعة للواجهة (RTL): `/`، `/landing`، `/marketers`، `/strategy`، `/login`، `/register`، `/dashboard`، `/settings`، `/privacy`، `/terms`
|
||||||
|
|
||||||
|
## 4) قنوات حقيقية
|
||||||
|
|
||||||
|
لا تفعّل واتساب/بريد إنتاجي حتى اكتمال فحوص PDPL والموافقات. للـ staging اختبر عنواناً داخلياً أو رقم sandbox.
|
||||||
4
salesflow-saas/frontend/.env.staging.example
Normal file
4
salesflow-saas/frontend/.env.staging.example
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Staging — copy to `.env.local` (or set in hosting dashboard). Do not commit `.env.local`.
|
||||||
|
# Must be a URL the browser can reach (HTTPS in staging/production).
|
||||||
|
|
||||||
|
NEXT_PUBLIC_API_URL=https://api-staging.example.com
|
||||||
31
salesflow-saas/memory/runbooks/ROLLBACK_AND_GO_LIVE.md
Normal file
31
salesflow-saas/memory/runbooks/ROLLBACK_AND_GO_LIVE.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Dealix — بوابة الإنتاج، المراقبة، والتراجع
|
||||||
|
|
||||||
|
**مرجع:** `docs/LAUNCH_CHECKLIST.md`، `GET /api/v1/autonomous-foundation/integrations/go-live-gate`، `GET /api/v1/autonomous-foundation/integrations/live-readiness`.
|
||||||
|
|
||||||
|
## ما قبل القطع (go-live gate)
|
||||||
|
|
||||||
|
1. دمج `main` مع CI أخضر (باكند pytest، فرونت lint/build، Playwright E2E).
|
||||||
|
2. Postgres: `make migrate` (أو ما يعادله في الاستضافة) — **لا** تعتمد على `init_db()` في SQLite للإنتاج.
|
||||||
|
3. ضبط `.env` و`frontend/.env.local` (`NEXT_PUBLIC_API_URL`، `FRONTEND_URL`، CORS).
|
||||||
|
4. توقع **403** من `go-live-gate` حتى تكتمل التكاملات الحرجة — هذا متوقع إذا كانت البيئة غير مهيأة بالكامل؛ راجع `live-readiness` للتفاصيل.
|
||||||
|
|
||||||
|
## النشر
|
||||||
|
|
||||||
|
- باكند: صورة Docker أو عملية `uvicorn` خلف reverse proxy مع TLS.
|
||||||
|
- فرونت: بناء Next.js (`npm run build`) أو منصة الاستضافة المختارة؛ نفس متغيرات الـ API العامة.
|
||||||
|
|
||||||
|
## المراقبة بعد الإطلاق
|
||||||
|
|
||||||
|
- `GET /api/v1/health` — الخدمة حية.
|
||||||
|
- `GET /api/v1/ready` — جاهزية التبعيات (قاعدة، Redis، إلخ حسب التطبيق).
|
||||||
|
- سجلات الأخطاء (مثلاً Sentry) ومراقبة معدل 5xx على المسارات الحرجة.
|
||||||
|
|
||||||
|
## التراجع (rollback)
|
||||||
|
|
||||||
|
1. **التطبيق:** إعادة نشر الإصدار السابق من صورة Docker / commit المعتمد.
|
||||||
|
2. **قاعدة البيانات:** إن وُجدت ترحيلات Alembic تسبب خللاً، نفّذ `alembic downgrade` إلى المراجعة المعروفة بالاستقرار (بعد أخذ نسخة احتياطية).
|
||||||
|
3. **الإعدادات:** أعد القيم السابقة للأسرار في مدير الأسرار إن تغيّرت أثناء القطع.
|
||||||
|
|
||||||
|
## فرع الكود للنشر
|
||||||
|
|
||||||
|
استخدم **`main`** كمصدر للإنتاج بعد الدمج؛ لا تعتمد على فروع مؤقتة قديمة في سكربتات النشر.
|
||||||
@ -41,7 +41,7 @@ apt install git -y
|
|||||||
# 5. انسخ المشروع
|
# 5. انسخ المشروع
|
||||||
git clone https://github.com/VoXc2/system-prompts-and-models-of-ai-tools.git
|
git clone https://github.com/VoXc2/system-prompts-and-models-of-ai-tools.git
|
||||||
cd system-prompts-and-models-of-ai-tools
|
cd system-prompts-and-models-of-ai-tools
|
||||||
git checkout claude/complete-system-prompts-wqJCm
|
git checkout main
|
||||||
cd salesflow-saas
|
cd salesflow-saas
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user