Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
30c1014
fix(ui): add team selector to agent profile modal and fix missing nav…
JOY Sep 2, 2026
dc415ec
feat(channels): add discord and facebook messenger omnichannel integr…
JOY Sep 2, 2026
ed1788b
feat(config): add discord and facebook messenger environment variable…
JOY Sep 2, 2026
58d52ea
feat: auto-provision 1-to-1 agent profile and simplify email channel …
JOY Sep 2, 2026
cea32a8
feat(channel): simplify email channel setup to only support email add…
JOY Sep 2, 2026
36eb023
feat(conversation): display channel icon, thread identifier, and subj…
JOY Sep 2, 2026
bc3f54c
chore(rules): add user interaction preferences for popup choice selec…
JOY Sep 2, 2026
961e0bb
feat(channels): auto subscribe messenger page webhook on channel save
JOY Sep 3, 2026
98d39b8
fix(docker): ignore flowgram-editor node_modules and build artifacts
JOY Sep 3, 2026
af555d4
feat(docker): configure supabase postgresql connection and remove loc…
JOY Sep 3, 2026
9ee2406
feat(auth): integrate JIT teams token claims and zero-latency organiz…
JOY Sep 3, 2026
527b3de
test(discord): add full end-to-end discord channel integration test
JOY Sep 3, 2026
13d9415
feat(channels): add instagram direct messaging omnichannel integration
JOY Sep 3, 2026
7637e14
fix(channel): derive human-friendly workspace slug for inbound forwar…
JOY Sep 3, 2026
a1215c4
feat(channels): add whatsapp business cloud api and slack workspace i…
JOY Sep 3, 2026
af3ed5d
feat(channels): add X and TikTok direct messaging channel support
JOY Sep 3, 2026
b153707
feat(email): support direct domain addressing and plus-addressing for…
JOY Sep 3, 2026
9441f59
feat(channels): complete X and TikTok webhook handlers, oauth routes,…
JOY Sep 3, 2026
996599b
feat(conversation): add single-select interactive assignee picker wit…
JOY Sep 3, 2026
3f1d055
feat(channel): use dedicated tenant subdomain format help@<slug>.crov…
JOY Sep 5, 2026
165eb76
fix(conversation): clean subject from body and fix filter queries for…
JOY Sep 5, 2026
05f1226
fix(services): correct sqls.Cnd condition for mine filter in conversa…
JOY Sep 5, 2026
0f809e1
feat(customer): implement Customer Merge dialog and backend API to co…
JOY Sep 6, 2026
e7425f9
feat(customer): display connected omnichannel channel badges and icon…
JOY Sep 6, 2026
fdf2b0e
Merge branch 'main' into dev
JOY Sep 7, 2026
d0cb879
feat(channels): add LINE, Viber, and Meta Threads messaging channels
JOY Sep 7, 2026
6a3b9c7
fix(channels): address code review findings for LINE, Viber, and Threads
JOY Sep 7, 2026
9a25b41
chore(repo): remove upstream submodules, version docs/ directly
JOY Sep 8, 2026
0cd8dd4
fix(repo): resolve fork-caused defects from code review audit
JOY Sep 8, 2026
bf79f85
docs(audit): record round-4 fixes and retract four claims
JOY Sep 8, 2026
95b32c6
fix(security): remove leaked API key fallback and correct KB multi-te…
JOY Sep 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .cursor/rules/user-interaction-preferences.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
description: Quy định tương tác và đề xuất lựa chọn bằng Popup/Form có cấu trúc (AskQuestion)
globs: *
alwaysApply: true
---
# User Interaction & Selection Preferences

## 1. Tương tác lựa chọn bằng Popup Form (`AskQuestion`)
- **KHÔNG BAO GIỜ** yêu cầu hoặc để người dùng phải gõ số text (ví dụ: `1`, `2`, `3`) để chọn phương án hay tác vụ, tránh triệt để nhầm lẫn hoặc lệch ngữ cảnh.
- **LUÔN LUÔN** gọi công cụ `AskQuestion` với popup lựa chọn trực quan (hỗ trợ `allow_multiple: true` khi có thể chọn nhiều task cùng lúc) mỗi khi:
- Báo cáo kết quả và đề xuất danh sách các task phát triển tiếp theo (Next Dev Tasks).
- Cần người dùng đưa ra quyết định kỹ thuật / lựa chọn phương án kiến trúc.
- Phân nhánh các hành động cần xác nhận.

## 2. Quy chuẩn Định dạng Văn bản (Formatting Cleanliness)
- **Tuyệt đối không sử dụng cú pháp LaTeX toán học** như `$\leftarrow$`, `$\rightarrow$` trong văn bản báo cáo hoặc giải thích vì sẽ bị lỗi render raw text xấu. Thay vào đó dùng các ký tự Unicode chuẩn như `←`, `→`, `->`, `<-`.

## 3. Tư duy thiết kế All-in-One Lean & AI-Native
- **Tránh bloatware/complex settings**: Không sao chép các hệ thống cài đặt rườm rà, thủ công hàng chục bước như Zendesk truyền thống.
- **Tự động hóa tối đa**: Tận dụng AI và cơ chế Zero-config / Auto-provisioning ngầm để người dùng không phải cấu hình thủ công nếu hệ thống có thể tự suy luận an toàn.
- **Giao diện tinh gọn**: Giữ UI hiện đại, tập trung vào trải nghiệm hội thoại đa kênh (Conversations-First).
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ config/config.yaml

node_modules
.pnpm-store
**/node_modules

flowgram-editor/node_modules
flowgram-editor/dist
flowgram-editor/.rsbuild

web/node_modules
web/.next
Expand Down
33 changes: 29 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ PORT=8083

# Database Configuration
# Driver options: sqlite, mysql, postgres
DB_TYPE=sqlite
DATABASE_URL=file:./data/app.db?_busy_timeout=5000
# Supabase PostgreSQL (DOS):
DB_TYPE=postgres
DATABASE_URL="host=aws-1-ap-southeast-1.pooler.supabase.com user=postgres.gulptwduchsjcsbndmua password=your-supabase-password dbname=postgres port=5432 sslmode=require search_path=desk"
# SQLite local:
# DB_TYPE=sqlite
# DATABASE_URL=file:./data/app.db?_busy_timeout=5000
# MySQL example:
# DATABASE_URL="cs_ai_agent:cs_ai_agent_password@tcp(127.0.0.1:3306)/cs_ai_agent?charset=utf8mb4&parseTime=True&multiStatements=true&loc=Local"
# PostgreSQL example:
# DATABASE_URL="postgres://postgres:password@127.0.0.1:5432/cs_ai_agent?sslmode=disable"

# Auth & Security
PASSWORD_LOGIN_ENABLED=true
Expand Down Expand Up @@ -92,3 +94,26 @@ BREVO_API_KEY=xkeysib-your-brevo-api-key
# MCP_ENABLED=true
# MCP_CRM_ENDPOINT=https://crm.crove.com/api/mcp
# MCP_CRM_API_KEY=your-twenty-crm-api-key

# Discord Channel & Bot Integration (SaaS Shared Bot or 1-Click OAuth)
# DISCORD_CLIENT_ID=your-discord-client-id
# DISCORD_CLIENT_SECRET=your-discord-client-secret
# DISCORD_BOT_TOKEN=your-discord-bot-token
# DISCORD_PUBLIC_KEY=your-discord-public-key

# Facebook Messenger Channel Integration (Meta Graph API)
# META_APP_ID=your-meta-app-id
# META_APP_SECRET=your-meta-app-secret
# MESSENGER_VERIFY_TOKEN=your-webhook-verify-token

# WhatsApp Cloud API Integration (Meta Graph API)
# WHATSAPP_ACCESS_TOKEN=your-whatsapp-system-user-token
# WHATSAPP_PHONE_NUMBER_ID=your-whatsapp-phone-number-id
# WHATSAPP_WABA_ID=your-whatsapp-business-account-id
# WHATSAPP_VERIFY_TOKEN=your-whatsapp-verify-token

# Slack Bot Integration (Slack Web API & Events API)
# SLACK_CLIENT_ID=your-slack-client-id
# SLACK_CLIENT_SECRET=your-slack-client-secret
# SLACK_BOT_TOKEN=xoxb-your-slack-bot-token
# SLACK_SIGNING_SECRET=your-slack-signing-secret
6 changes: 0 additions & 6 deletions .gitmodules

This file was deleted.

32 changes: 8 additions & 24 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
services:
mysql:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_DATABASE: cs_ai_agent
MYSQL_USER: cs_ai_agent
MYSQL_PASSWORD: cs_ai_agent_password
MYSQL_ROOT_PASSWORD: cs_ai_agent_root_password
TZ: Asia/Shanghai
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u\"$${MYSQL_USER}\" -p\"$${MYSQL_PASSWORD}\" --silent"]
interval: 10s
timeout: 5s
retries: 10

qdrant:
image: qdrant/qdrant:latest
restart: unless-stopped
Expand All @@ -32,22 +12,26 @@ services:
build:
context: .
dockerfile: Dockerfile
image: mlogclub/agent-desk:latest
image: crove-desk:latest
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
qdrant:
condition: service_started
ports:
- "8083:8083"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- agent-desk-data:/app/data
- ./docker/agent-desk.yaml:/app/config/config.yaml:ro
env_file:
- .env
environment:
TZ: Asia/Shanghai
QDRANT_HOST: qdrant
DB_TYPE: postgres
DATABASE_URL: "postgres://postgres:postgres@host.docker.internal:54322/postgres?sslmode=disable&search_path=desk"

volumes:
mysql-data:
qdrant-data:
agent-desk-data:
1 change: 0 additions & 1 deletion docs
Submodule docs deleted from 1c433f
213 changes: 213 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Crove Desk System Architecture (Crove OS Architecture)

This document defines the overall architecture of **Crove Desk** (`desk.crove.com`), an AI-first intelligent HelpDesk and Customer Support system, and its deep integration with the **Crove Business OS** ecosystem, including **Twenty CRM** (`crm.crove.com`), **Crove Sign**, **Crove Post**, **Crove Cal**, and **DOS.Me ID**.

---

## 1. High-Level Architecture: 2-Tier Hybrid Pattern

To achieve **instant UI response (< 5ms)**, **database foreign key constraints**, and **autonomous AI Agent actions**, the Crove OS ecosystem adopts a **2-Tier Hybrid Architecture**:

```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ CROVE OS 2-TIER HYBRID ARCHITECTURE │
├──────────────────────────────────────────┬──────────────────────────────────────────────┤
│ TIER 1: Identity & Relational Mirror │ TIER 2: Deep Agentic Business Actions │
│ (Companies, Customers, Organizations) │ (Create Deals, Quotas, Tasks, Contracts) │
├──────────────────────────────────────────┼──────────────────────────────────────────────┤
│ DATABASE SYNCHRONIZATION │ MCP PROTOCOL │
│ (PostgreSQL Mirror nội bộ < 5ms) │ (Model Context Protocol Tool Calling) │
│ │ │ │ │
│ • Twenty CRM: Master SSOT │ • twenty_crm.create_opportunity(...) │
│ • Crove Desk: desk.t_company / │ • twenty_crm.get_subscription_status(...) │
│ desk.t_customer │ • twenty_crm.create_task(...) │
│ • Bi-directional Webhook Dispatch │ • crove_sign.get_contracts(...) │
│ • JIT (Just-In-Time) Onboarding │ • Realtime dynamic side-effect execution │
└──────────────────────────────────────────┴──────────────────────────────────────────────┘
```

### Why Crove Desk Maintains a Local Database Mirror (`desk.t_company`, `desk.t_customer`):
1. **Foreign Key Integrity**: Tickets (`desk.t_ticket`), chat conversations (`desk.t_conversation`), CSAT ratings, and SLA policies require direct `ticket.customer_id` and `ticket.company_id` relational constraints. Foreign keys cannot cross HTTP/MCP boundaries.
2. **Instant UI Rendering (< 5ms Latency)**: When an agent opens an inbox or ticket, company names, contact numbers, avatars, and VIP badges load immediately from local PostgreSQL, eliminating network latency (200ms–600ms).
3. **High-Performance Search & Indexing**: Enables instant searching, sorting, and filtering across thousands of customer records and conversations.
4. **Fault Isolation**: If Twenty CRM undergoes maintenance or network hiccups, Crove Desk continues accepting support chats and managing tickets uninterrupted.

---

## 2. System Interaction Topology

```mermaid
flowchart TB
subgraph Client ["Clients & Users"]
Guest["Customers (Web Widget / Telegram / Zalo / Email)"]
Staff["Crove Team (Sales / Support / Founder)"]
end

subgraph FrontEnd ["Unified Frontend Layer"]
DeskUI["Crove Desk (desk.crove.com)<br/>Next.js 16 + React 19 + shadcn/ui + Tailwind v4"]
CRMUI["Crove CRM (crm.crove.com)<br/>Twenty React Shell"]
end

subgraph CoreEngine ["Business & AI Engine"]
DeskBack["AgentDesk Engine (Golang 1.26)<br/>RAG + Qdrant + AI Agent Loop + MCP Client"]
TwentyBack["Twenty CRM Engine (NestJS)<br/>Metadata ORM + Workflows + MCP Server"]
end

subgraph Storage ["Data & Storage Layer"]
SupaDB[("Supabase PostgreSQL (dos.me)<br/>Schema: desk / custom role: desk_app")]
QdrantDB[("Qdrant Vector DB<br/>Embeddings & Knowledge Base")]
StorageS3[("Object Storage / Local Storage")]
end

subgraph IntegrationBridge ["Integration & Sync Hub"]
MCP["MCP Protocol (twenty_crm & system tools)"]
EventRouter["DOS.Me Event Router Hub<br/>(https://api.dos.me/internal/events/publish)"]
JIT["OIDC / OAuth 2.1 PKCE JIT Sync"]
end

Guest --> DeskUI
Staff --> DeskUI
Staff --> CRMUI

DeskUI <--> DeskBack
CRMUI <--> TwentyBack

DeskBack --> SupaDB
DeskBack --> QdrantDB
DeskBack --> StorageS3

DeskBack <==> MCP <==> TwentyBack
DeskBack <==> EventRouter <==> TwentyBack
DeskBack <==> JIT <==> SupaDB
```

---

## 3. Four Core Integration Layers

### 3.1. Layer 1: Deep Agentic MCP Tool Calling
Bidirectional Model Context Protocol (MCP) communication between AI Agents:
* **Crove Desk AI -> Twenty CRM MCP**:
* `twenty_crm.get_subscription_status`: Query active plans, quotas, and expiration dates.
* `twenty_crm.create_opportunity`: Automatically create enterprise deals when a customer expresses buying intent.
* `twenty_crm.create_task`: Schedule consultative demo calls for assigned account executives.
* **Crove Desk AI -> Crove Sign MCP**:
* `crove_sign.get_contracts`: Check status of electronic agreements and pending signatures.

### 3.2. Layer 2: Real-time Event-Driven Webhook Sync (HMAC Verified)
When entities change in Twenty CRM or Crove Desk, events publish to `api.dos.me/internal/events/publish` and route to subscribers with `X-DOS-Signature: sha256=<hex_digest>` verification:
* `company.created` / `company.updated`: Syncs company profiles, domain names, and tiers.
* `customer.created` / `customer.updated`: Syncs customer names, emails, phones, job titles, and avatars.
* `organization.created` / `organization.updated`: Syncs multi-tenant workspaces.
* `organization.member.added` / `organization.member.removed`: Syncs team memberships and roles (`OWNER`, `ADMIN`, `MEMBER`).

### 3.3. Layer 3: Omnichannel Communication Gateway
Native inbound/outbound channel adapters normalize messages into the `Message Inbound Queue`:
* **Web Chat Widget**: Embeddable JavaScript SDK (`agent-desk-sdk.min.js`) with responsive desktop & mobile support.
* **Native Telegram Channel** *(In Progress)*: Direct Telegram Bot Webhook adapter (`/api/channels/telegram/webhook`) routing chats to agents and AI loop.
* **Zalo Official Account (OA)**: Webhook adapter for Vietnamese enterprise support.
* **Inbound Email Support**: IMAP / transactional email parsing into conversation tickets.

### 3.4. Layer 4: UI Embedding & Contextual Sidebars
* **Support Tab inside Twenty CRM**: Twenty App Widget SDK embedding real-time support history inside customer CRM profiles.
* **CRM Customer Sidebar in Desk Workspace**: Displays customer MRR, active plan, deal stage, and assigned account manager directly in the live agent workbench.

---

## 4. AI Support Lifecycle Flow & Answerability Gate

```mermaid
flowchart TD
A[Customer sends a message<br/>Web Widget / Telegram / Zalo] --> B[Initialize / Match Customer Identity]
B --> C[Check Customer Record in Local PostgreSQL Mirror]
C --> D[Trigger AI Agent Reply Runtime]
D --> E[Retrieve Embeddings from Qdrant Vector DB]
E --> F{Answerability Gate<br/>Sufficient Evidence?}
F -- Insufficient --> G[Return Fallback Message & Recommend Human Support]
F -- Sufficient --> H[Prepare MCP Tools & Knowledge Context]
H --> I{External MCP Tool Required?}
I -- Yes --> J[Invoke Twenty CRM / Crove Sign MCP Tool]
J --> K{Requires Human Confirmation?}
K -- Yes --> L[Prompt Agent / User to Confirm]
K -- No --> M[Generate Knowledge-Grounded Answer]
L --> M
I -- No --> M
G --> N[Move Conversation to Human Handoff Queue]
N --> O[Human Agent Takes Over via Workspace]
O --> P{Create Follow-up Ticket?}
P -- Yes --> Q[Convert to Ticket & Sync to Twenty CRM Activity Timeline]
P -- No --> R[Resolve Directly & Close Conversation]
Q --> R
```

---

## 5. Technology Stack & Infrastructure

| Component | Technology | Details |
| :--- | :--- | :--- |
| **Backend Framework** | Golang (Go 1.26+) + Gin | High-concurrency async runtime, streaming WebSockets, REST APIs |
| **Data Layer** | GORM + `github.com/mlogclub/simple` | Clean layer ownership: `models -> repositories -> services -> handlers` |
| **Primary Database** | PostgreSQL (Supabase `dos.me`) | Schema `desk`, managing conversations, tickets, customers, users, orgs |
| **Vector Database** | Qdrant (`6333` REST / `6334` gRPC) | Vector embedding storage for Knowledge Base semantic retrieval |
| **AI Runtime** | OpenAI-compatible API (DOS.AI / OpenAI / DeepSeek) | Agent Loop orchestration, Answerability Gate, and MCP Tool calling |
| **Frontend** | Next.js 16 (Turbopack) + React 19 + Tailwind v4 + shadcn | Responsive Dashboard, Workbench, and Support Center (`en-US`, `vi-VN`, `zh-CN`) |
| **Hosting & Network**| GCP VM `crove-server` + Cloudflare Tunnel | High-availability Docker stack mapped to `desk.crove.com` |

---

## 6. DOS.Me Hierarchy Standard & Multi-Product Sync (Org -> Team / Project)

To maintain consistent multi-tenant organizational structure across all Crove OS member applications, DOS.Me acts as the central Identity & Organization Authority.

### 6.1. Cross-Product Entity Mapping Matrix

| DOS.Me Concept (SSOT) | Crove Desk (`desk.crove.com`) | Crove CRM (`crm.crove.com`) | Crove Sign (`sign.crove.com`) | Crove Post (`post.crove.com`) | Crove Cal (`cal.crove.com`) |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **Organization (Tenant)** | `t_organization` | `Workspace` (`core.workspace`) | `Organisation` (`sign.organisation`)| `Organization` (`post.organization`) | `Organization` (`cal.organization`) |
| **Project / Team (Sub-unit)** | `t_agent_team` (Support Team) | `Group` / `Team` | `Team` (`sign.team`) | `Workspace Team` | `Team` (`cal.team`) |
| **User (Account)** | `t_user` + `t_agent_profile` (1:1)| `User` (`core.user`) | `User` (`sign.user`) | `User` (`post.user`) | `User` (`cal.user`) |

### 6.2. Two-Phase Synchronization Standard (JIT + Real-time Webhooks)

#### Phase 1: Just-In-Time (JIT) Provisioning upon OIDC Login
When a user logs in via DOS.Me OIDC, the `userinfo` claim supplies both organization and team memberships:
```json
{
"sub": "usr_dos_123456",
"email": "joy@dos.ai",
"name": "Anh Le",
"picture": "https://avatar.dos.me/joy.png",
"organizations": [
{
"id": "org_dos_9988",
"name": "DOS Corporation",
"role": "ADMIN",
"teams": [
{ "id": "proj_support_01", "name": "Customer Support", "slug": "support" },
{ "id": "proj_sales_02", "name": "Sales & Success", "slug": "sales" }
]
}
]
}
```
* **Crove Desk Action**: Automatically ensures `t_organization`, provisions default/mapped `t_agent_team`, creates `t_user`, and guarantees 1-to-1 `t_agent_profile` association.

#### Phase 2: Real-time Event-Driven Webhooks (`X-DOS-Signature: sha256=...`)
When administrators create, update, or reorganize Teams/Projects in DOS.Me, webhook events are broadcast to member apps:
```json
{
"event": "team.member_added",
"timestamp": "2026-09-02T14:45:00Z",
"data": {
"org_id": "org_dos_9988",
"team_id": "proj_support_01",
"team_name": "Customer Support",
"user_id": "usr_dos_123456",
"user_email": "joy@dos.ai",
"role": "ADMIN"
}
}
```
* **Supported Team Events**: `team.created`, `team.updated`, `team.deleted`, `team.member_added`, `team.member_removed`.

Loading
Loading