EternalAI/README.md

307 lines
13 KiB
Markdown
Raw Permalink 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.

# Eternal AI
AI 陪伴平台 — 人设创作者设定并发布角色,自动生成 Hermes Agent 可用的配置文件SOUL.md + config.yaml支持跨机器 CLI 拉取部署。
## 架构
```
┌──────────────────────────────────────────────────────────┐
│ 浏览器 (SPA) │
│ index.html + app.js + styles.css │
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 认证视图 │ │ 角色库 │ │ 创作者中心 │ │ 角色编辑器 │ │
│ └──────────┘ └──────────┘ └───────────┘ └───────────┘ │
└──────────────────────┬───────────────────────────────────┘
│ HTTP / JSON
┌──────────────────────▼───────────────────────────────────┐
│ Express.js 服务端 (server.js) │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ /api/auth│ │/api/roles│ │/api/apikeys│ │ /api/hermes │ │
│ └────┬────┘ └────┬────┘ └─────┬────┘ └──────┬────────┘ │
│ │ │ │ │ │
│ ┌────▼───────────▼────────────▼──────────────▼────────┐ │
│ │ 认证中间件 (src/lib/auth.js) │ │
│ │ JWT 认证 (authMiddleware) + API Key 认证 │ │
│ │ (apiKeyMiddleware, eak_ 前缀, SHA-256 哈希) │ │
│ └─────────────────────┬───────────────────────────────┘ │
└────────────────────────┼─────────────────────────────────┘
│ Prisma ORM
┌────────────────────────▼─────────────────────────────────┐
│ PostgreSQL 数据库 │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ User │ │ Role │ │ ApiKey │ │ Order │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ │
└──────────────────────────────────────────────────────────┘
```
### 技术栈
| 层 | 技术 |
|----|------|
| 前端 | 原生 HTML5 SPAIIFE 模式,无框架)、玻璃拟态 UI |
| 后端 | Node.js + Express 5.x |
| 数据库 | PostgreSQL 15 + Prisma ORM 5.x |
| 认证 | JWT7 天有效期)+ API Key`eak_` 前缀SHA-256 哈希存储) |
| 密码 | bcryptjs10 轮盐) |
| 测试 | Playwright E2E35 个测试用例) |
| 部署 | PM2 + Nginx 反向代理 |
### 项目结构
```
EternalAI/
├── server.js # Express 入口,注册路由 + 静态文件
├── app.js # 前端 SPA 逻辑路由、状态、表单、API 调用)
├── index.html # 单页应用入口9 个视图)
├── styles.css # 玻璃拟态样式
├── prisma/
│ └── schema.prisma # 数据模型定义User / Role / ApiKey / Order
├── src/
│ ├── lib/
│ │ ├── auth.js # JWT + API Key 认证中间件
│ │ └── prisma.js # Prisma Client 单例
│ └── routes/
│ ├── auth.js # 注册 / 登录 / 用户信息 / 设置
│ ├── roles.js # 角色 CRUD + 角色库
│ ├── apikeys.js # API Key 生成 / 列表 / 删除
│ └── hermes.js # Hermes 配置拉取端点SOUL.md / config.yaml
├── deploy/
│ ├── setup-server.sh # 服务器一键初始化脚本
│ ├── deploy.sh # CI/CD 部署脚本
│ └── nginx.conf # Nginx 反向代理配置
├── e2e/ # Playwright E2E 测试
├── docs/ # 需求文档与规划
└── package.json
```
## 快速开始
### 本地开发
```bash
# 1. 安装依赖
npm install
# 2. 配置环境变量
cp .env.example .env
# 编辑 .env设置 DATABASE_URL 和 JWT_SECRET
# JWT_SECRET 可用 openssl rand -hex 32 生成
# 3. 初始化数据库
npx prisma db push
npx prisma generate
# 4. 启动开发服务器
npm run dev
# → http://localhost:3001
```
### 服务器部署
```bash
# 在服务器上执行一键初始化脚本
bash deploy/setup-server.sh
# 自动安装 Node.js / PostgreSQL / Nginx / PM2创建 .env推送 Schema
```
## 操作流程
### 1. 用户注册与登录
```
用户 → 首页 → 登录/注册视图
├─ 注册:填写账号 + 密码≥6位→ 自动登录,返回 JWT
└─ 登录:账号 + 密码 → 验证成功,返回 JWT
└─ JWT 存入 localStorage后续请求携带 Authorization: Bearer <token>
```
### 2. 创作者入驻与角色设定
```
登录用户 → 创作者入驻页 → 开通创作者身份
→ 创作者管理中心(三个 Tab
├─ 角色 Tab新建 / 编辑角色
├─ 收入 Tab余额 + 付费流水
└─ 设置 Tab昵称 / 角色库名 / API Key 管理
新建角色4 步表单):
Step 1 → 基础信息(名称、性别、年龄、关系)
Step 2 → 性格设定(性格、背景、说话风格、喜好)
Step 3 → 模型配置(模型、温度、最大 Token、记忆/工具开关)
Step 4 → 发布设置(问候语、价格、描述)
→ 提交后自动生成 SOUL.md + config.yaml 存入数据库
→ 角色上架到角色库
```
### 3. 角色库浏览与购买
```
任意用户 → 角色库 → 浏览已上架角色
→ 点击角色卡片 → 查看详情
→ 付款 → 创建订单 → 解锁角色
```
## 与 Hermes Agent 交互流程
EternalAI 生成的角色配置SOUL.md + config.yaml可通过 CLI 拉取命令部署到任意 Hermes Agent 机器上,支持跨机器部署。
### 架构图
```
服务器 A (EternalAI) 服务器 B (Hermes Agent)
┌───────────────────────┐ ┌───────────────────────┐
│ 1. 设置页生成 API Key │ │ │
│ (eak_xxxxxxxxxx) │ │ 5. hermes profile │
│ │ │ create role-mio │
│ 2. 创建角色 → 发布 │ │ │
│ 生成 SOUL.md + │ │ 6. curl 拉取文件 │
│ config.yaml │ │ SOUL.md │
│ │ │ config.yaml │
│ 3. 角色管理页显示 │ 4. 用户复制 │ │
│ curl 命令模板 │──── curl ────▶│ 7. 配置 .env │
│ (含 API Key) │ 命令执行 │ (API 密钥) │
│ │ │ │
│ │ │ 8. role-mio chat │
└───────────────────────┘ └───────────────────────┘
```
### 步骤详解
#### Step 1-3在 EternalAI Web UI 操作
1. **生成 API Key**:创作者管理中心 → 设置 Tab → 点击「生成 API Key」→ 明文 Key 仅显示一次,请妥善保存
2. **创建角色**:创作者管理中心 → 角色 Tab → 新建角色 → 填写 4 步表单 → 发布
3. **获取部署命令**角色卡片点击「Hermes 部署」→ 弹窗显示完整的 curl 命令模板(含服务器地址、角色 ID、API Key→ 点击复制
#### Step 4-8在 Hermes Agent 机器上操作
```bash
# 4. 复制 curl 命令到 Hermes 机器执行
# 5. 创建 Hermes profile
hermes profile create role-mio
# 6. 拉取 SOUL.md
curl -H "Authorization: Bearer eak_xxx" \
https://your-eternalai-domain.com/api/hermes/roles/<role-id>/SOUL.md \
-o ~/.hermes/profiles/role-mio/SOUL.md
# 7. 拉取 config.yaml
curl -H "Authorization: Bearer eak_xxx" \
https://your-eternalai-domain.com/api/hermes/roles/<role-id>/config.yaml \
-o ~/.hermes/profiles/role-mio/config.yaml
# 8. 配置 API 密钥并启动
echo "OPENROUTER_API_KEY=sk-or-xxx" > ~/.hermes/profiles/role-mio/.env
role-mio chat
```
### config.yaml 格式适配
EternalAI 角色数据自动转换为 Hermes config.yaml 格式:
| EternalAI 字段 | Hermes config.yaml 字段 |
|---|---|
| `role.model` | `model:` |
| `role.temperature` | `temperature:` |
| `role.maxTokens` | `max_tokens:` |
| `role.enableMemory` | `memory.enabled:` |
| `role.enableTools` | `tools.enabled:` |
生成的 config.yaml 示例:
```yaml
# Hermes Agent Config — generated by EternalAI
# Character: Mio
# Agent ID: default
# Generated at: 2026-06-21T12:00:00.000Z
model: "gpt-4o"
temperature: 0.85
max_tokens: 2048
memory:
enabled: true
storage: local
tools:
enabled: true
toolsets:
- memory
terminal:
backend: local
```
### API Key 安全机制
- **格式**`eak_` + 32 位随机 hex128 位熵)
- **存储**SHA-256 哈希存储,明文仅在生成时返回一次
- **脱敏显示**:列表中仅显示前 12 位(如 `eak_a1b2c3d4`
- **认证**:通过 `Authorization: Bearer eak_xxx` 头传递
- **权限**API Key 只能拉取所属用户创建的角色配置
- **可吊销**:随时在设置页删除,删除后立即失效
## API 参考
### 认证 API
| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| POST | `/api/auth/register` | 无 | 注册(账号 + 密码) |
| POST | `/api/auth/login` | 无 | 登录 |
| GET | `/api/auth/me` | JWT | 获取当前用户信息 |
| PUT | `/api/auth/settings` | JWT | 更新用户设置 |
### 角色 API
| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| GET | `/api/roles` | 无 | 获取角色库(已上架) |
| GET | `/api/roles/:id` | 无 | 获取角色详情 |
| GET | `/api/roles/my/roles` | JWT | 获取我创建的角色 |
| POST | `/api/roles` | JWT | 发布新角色 |
| PUT | `/api/roles/:id` | JWT | 编辑角色 |
| GET | `/api/roles/:id/full` | JWT | 获取角色完整信息(含 SOUL.md |
### API Key 管理
| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| POST | `/api/apikeys` | JWT | 生成 API Key明文仅返回一次 |
| GET | `/api/apikeys` | JWT | 列出所有 API Key脱敏 |
| DELETE | `/api/apikeys/:id` | JWT | 删除 API Key |
### Hermes 配置拉取
| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| GET | `/api/hermes/roles/:id/SOUL.md` | API Key / JWT | 拉取 SOUL.mdtext/plain |
| GET | `/api/hermes/roles/:id/config.yaml` | API Key / JWT | 拉取 config.yamltext/plain |
## 测试
```bash
# 运行全部 E2E 测试35 个用例)
npm test
# 查看测试报告
npx playwright show-report
```
测试覆盖:认证流程、角色发布/编辑、角色库浏览、导航与可访问性。
## 安全
- **JWT 密钥**:生产环境必须设置 `JWT_SECRET` 环境变量,未设置时 fail-fast 抛错
- **密码存储**bcrypt 哈希10 轮盐),不存明文
- **API Key 存储**SHA-256 哈希存储,明文仅显示一次
- **XSS 防护**:所有用户可控数据通过 `escapeHtml()` 转义后插入 DOM
- **YAML 注入防护**config.yaml 生成时对用户可控字段做双引号转义和换行符过滤
- **所有权校验**:所有角色操作验证 `creatorId === req.userId`
- **.env 文件权限**:部署脚本自动设置 `chmod 600`
## License
MIT