# libredesk(crm-new/libredesk) 位于 `/home/dev/code/crm-new/libredesk` 的 **LibreDesk 版 CRM 客服栈**,与旧项目 `/home/dev/code/crm/crm-ai-demo` 完全隔离(独立目录、独立 git、独立 Postgres/Redis、独立端口)。 - **定位**:验证「LibreDesk 作为客服平台 + 内置 AI Assistant + 外部业务工具」能否替代现有 Chatwoot + bridge 架构。 - **当前阶段**:POC 骨架(可启动、工具服务可跑、含单元测试),尚未接入真实 widget 和生产数据。 - **旧系统不受影响**:`crm-ai-demo` 仍在 3000/3001/4000 端口运行。 ## 当前状态(2026-10-21) | 项 | 状态 | |---|---| | 目录/配置/脚本脚手架 | ✅ 完成 | | crm-tools 服务(4 工具 + 鉴权 + 验证门控) | ✅ 单测 18/18 通过,本机 :4010 可运行 | | config.toml 渲染 / compose 校验 | ✅ 通过 | | LibreDesk 容器 | ✅ 运行中(**v2.9.0-rc.10**,health 200);Postgres 18 / Redis 健康 | | 后台 AI/工具/助手配置 | ⏳ 登录 `http://localhost:9000` 后按 `docs/libredesk-setup.md` 执行 | > 当前运行 **v2.9.0-rc.10**:渠道已包含 `email / livechat / whatsapp`,WhatsApp 表已迁移完成。 > RC 属于预发布版本,功能可用但生产使用前需评估稳定性(回滚方法见「镜像拉取」)。 ## 架构 ``` 访客 ──► LibreDesk Live Chat Widget (:9000) │ ▼ LibreDesk AI Assistant ──HTTP tool calls──► crm-tools (:4010) (snippets 向量检索 / 内置 OTP 验证) │ ├──► 商品推荐 RPC (recommend) ├──► 订单 RPC (trading-service) ├──► 库存/ETA RPC (eta-service) └──► Twenty CRM GraphQL (商机/备注/任务) ``` 关键设计:**业务数据与身份验证不放进 LibreDesk 代码里**,而是通过它的自定义 HTTP 工具回调 `crm-tools`;工具服务二次校验 `X-Libredesk-Contact-Verified`,不信任模型参数里的邮箱。 详见 [docs/architecture.md](docs/architecture.md)。 ## 目录 ``` crm-new/libredesk/ ├── docker-compose.yml # LibreDesk + 独立 Postgres(5433) + Redis(6380) ├── .env.example # 环境变量模板(bootstrap 自动生成 .env) ├── config/ │ └── config.toml.example # LibreDesk 配置模板(渲染成 config.toml,不入库) ├── scripts/ │ ├── bootstrap.sh # 生成密钥 + 渲染配置 + 启动 LibreDesk │ ├── start-tools.sh # 宿主机启动 tools 服务 │ ├── render-config.js # config.toml 渲染 │ ├── register-tools.js # 把工具注册进 LibreDesk(可选) │ └── smoke.sh # 冒烟测试 ├── services/tools/ # 业务工具服务(Node 20+,零外部依赖) │ ├── src/ │ │ ├── server.js # HTTP 入口 + 鉴权 + 验证门控 │ │ ├── tools.js # 4 个工具:商品/订单/库存/建商机 │ │ ├── twenty.js # Twenty GraphQL 客户端 │ │ ├── rpc.js # JSONRPC-TCP 客户端(Hyperf 协议) │ │ ├── config.js / auth.js / errors.js │ └── test/ # node:test 单元测试 ├── docs/ │ ├── architecture.md # 架构与数据流 │ ├── libredesk-setup.md # 后台配置步骤(AI/工具/助手/自动化/Widget) │ ├── api-mapping.md # Chatwoot → LibreDesk 接口/事件/字段对照 │ └── migration-plan.md # 6 层拆分、方案 A/B/C、代码存废清单 ├── deploy/nginx.conf.example └── uploads/ # LibreDesk 上传目录(运行时) ``` ## 快速开始 > 网络提示:本机直连 Docker Hub 会 reset。`.env` 已默认复用本地已有镜像 > (`pgvector/pgvector:pg18`、`redis:8.8-alpine`),LibreDesk 镜像可用时可改 > `LIBREDESK_IMAGE=docker.1panel.live/libredesk/libredesk:latest` 等镜像源。 > 详见文末「镜像拉取」一节。 ```bash cd /home/dev/code/crm-new/libredesk # 1) 启动 LibreDesk(自动生成 .env / config.toml,首次拉镜像) bash scripts/bootstrap.sh # 2) 另开终端,启动工具服务 :4010 bash scripts/start-tools.sh # 3) 按 docs/libredesk-setup.md 配置 AI Provider / Inbox # 然后在 Admin → Teammates → System 生成 API key,填入 .env # 4) 自动注册 4 个 AI 工具(失败也可按文档手工创建) node scripts/register-tools.js # 5) 冒烟 bash scripts/smoke.sh ``` | 组件 | 地址 | 说明 | |---|---|---| | LibreDesk | http://localhost:9000 | `System` + bootstrap 生成的密码 | | crm-tools | http://127.0.0.1:4010 | `/healthz`、`/tools/manifest`、`/tools/` | | Postgres | 127.0.0.1:5433 | 独立实例,库 `libredesk` | | Redis | 127.0.0.1:6380 | 独立实例 | ## 工具清单 | 工具 | 需要验证 | 作用 | |---|---|---| | `search_products` | 否 | 商品关键词搜索(recommend RPC) | | `search_orders` | **是** | 订单/物流查询,邮箱强制取自已验证身份头 | | `search_inventory` | 否 | SKU 实时库存 + ETA | | `create_opportunity` | **是** | Twenty 建商机 + 聊天摘要备注 + 3 天跟进任务,按邮箱去重 | ## 测试 ```bash cd services/tools && npm test ``` 覆盖:地址解析、鉴权 fail-closed、验证门控、邮箱作用域/IDOR 防护、商机去重。 ## 本阶段边界(未做) - 未接入真实网站 widget(JWT 签发仍是下一步) - 未做 Chatwoot → LibreDesk 数据迁移(当前旧库仅 2 条会话,可忽略) - 未接入观测/评估/飞轮(需要时按 [docs/migration-plan.md](docs/migration-plan.md) 的 L6 保留 bridge) - WhatsApp 需 v2.9 预发布版(见 setup 文档最后一节) ## 镜像拉取(国内网络) 本机实测:`registry-1.docker.io` 连接被 reset,直连不可用。 | 方案 | 命令 | 备注 | |---|---|---| | 1panel 镜像源 | `docker pull docker.1panel.live/libredesk/libredesk:v2.9.0-rc.10` | ✅ 2026-10-21 实测可用(74MB) | | 稳定版 latest | `docker pull docker.1panel.live/libredesk/libredesk:latest` | ✅ 可用(= v2.8.0,无 WhatsApp) | | 1ms 镜像源 | `docker pull docker.1ms.run/libredesk/libredesk:latest` | 备用 | | 自建(不推荐) | 从 `v2.8.0` 源码构建 | 需要 Go + Node + pnpm,耗时较长 | 拉到镜像后改 `.env`: ```ini LIBREDESK_IMAGE=docker.1panel.live/libredesk/libredesk:v2.9.0-rc.10 # 或本地打 tag 后继续用默认值 # docker tag docker.1panel.live/libredesk/libredesk:v2.9.0-rc.10 libredesk/libredesk:v2.9.0-rc.10 ``` ### 回滚到稳定版 v2.8.0 ```bash sed -i 's#^LIBREDESK_IMAGE=.*#LIBREDESK_IMAGE=docker.1panel.live/libredesk/libredesk:latest#' .env docker compose up -d --force-recreate app # 跨版本回退需用备份库,见下 ``` ## 与旧系统的关系 | | 旧栈 `crm-ai-demo` | 新栈 `crm-new/libredesk` | |---|---|---| | 客服平台 | Chatwoot 4.16(Rails) | LibreDesk(Go 单二进制) | | AI 编排 | bridge 自研 agent loop | LibreDesk AI Assistant(POC 目标) | | 业务工具 | bridge 内置 | 独立 `services/tools` | | 数据 | crm-postgres:5432 | 独立 postgres:5433 | | 端口 | 3000/3001/4000 | 9000/4010 | 两套可以并行跑,方便同一批问题做 A/B 对比。