Files
agent/README.md

231 lines
11 KiB
Markdown
Raw 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.
# 森林AI
## 产品定位
森林AI 是一个以项目为中心、面向私有化部署的工作台 MVP服务于个人知识工作者、团队负责人和可信的内部用户。它把项目、任务、Inbox 收集、Markdown 笔记、文件资料、AI 会话、项目内标签和轻量任务分发组织在同一工作区中。
Web 客户端桌面优先,同时保留移动浏览器可用性;登录页允许输入私有部署服务器的 IP 地址或域名。
## MVP 范围
当前版本包含:
- 项目创建、设置和聚合工作区。
- 项目内任务、标签、文件资料和计划任务元数据。
- Inbox 收集、分析建议和用户确认创建对象的流程。
- 项目、任务和笔记的关键词搜索。
- 项目内 AI 会话入口、密钥选择、限流与调用审计。
- React Web 客户端和 Tauri 桌面壳。
当前版本不包含实时即时通讯、项目级成员角色体系、匿名公开分享、自主 Agent 执行、语义或向量搜索、第三方数据源集成、原生移动 App、浏览器扩展、离线编辑或本地优先同步。
## 技术栈
- 后端Go 1.26.1、Gin、Gorm、PostgreSQL 16。
- WebReact 18、TypeScript、Vite 8、Arco Design。
- 桌面端Tauri 2、Rust stable共用 Web 构建产物。
- 本地基础设施Docker Compose。
本仓库当前验证环境使用 Node.js 24.11.0、npm 11.12.1、Rust 1.97.1;其他版本应满足各锁文件与工具链要求。
## 目录结构
```text
.
├── backend/ # Go API、数据库模型、业务逻辑和演示数据
│ ├── cmd/api/ # API 入口
│ ├── cmd/seed/ # 开发演示数据入口
│ ├── etc/ # 按模式加载的 YAML 配置
│ └── internal/ # httpx、models 与各业务包
├── apps/web_v1/ # React + TypeScript 主 Web 客户端
├── apps/desktop/ # Tauri 桌面壳
├── infra/docker-compose.yml # 本地 PostgreSQL 16
└── docs/ # 规格、计划与 MVP 验证说明
```
## 快速开始
### 1. 准备环境
安装 Go、Node.js/npm 和 Docker Desktop并确保 Docker Desktop 已启动。桌面端构建还需要 Rust stable 与平台编译工具链。
### 2. 启动 PostgreSQL
在任意仓库子目录运行:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location $repoRoot
docker compose -f infra/docker-compose.yml up -d
```
Compose 只用于本地开发,创建 PostgreSQL 16 服务并监听 `localhost:5432`。其中的默认数据库凭据不得用于生产环境。
### 3. 初始化演示数据
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'backend')
go run ./cmd/seed
```
默认演示账号为 `demo@senlin.ai`,默认密码为 `password123`。它们只用于本地开发;生产部署必须创建正式用户并替换所有默认凭据与密钥。
### 4. 启动 API
在新的终端中运行:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'backend')
go run ./cmd/api
```
开发配置默认监听 `http://localhost:9150`。可用 `GET /healthz` 检查进程健康状态Web 登录页使用 `GET /api/v1/status` 检查服务器连接。
### 5. 启动 Web 客户端
在新的终端中运行:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'apps/web_v1')
npm ci
npm run dev
```
Vite 默认地址为 `http://localhost:5173`。登录页的服务器地址默认是 `http://localhost:9150`;用户可以改为私有部署服务器的 IP 地址或域名,登录及后续 API 请求会使用用户填写的地址。
## 配置
后端从 `backend/etc/agent.<mode>.yaml` 读取配置。`SENLIN_APP_MODE` 未设置时使用 `backend/etc/agent.dev.yaml`;例如设置 `$env:SENLIN_APP_MODE='prod'` 时读取 `backend/etc/agent.prod.yaml`,该生产文件需由部署方安全提供。
| 字段 | 用途 |
| --- | --- |
| `env` | 运行环境标识。 |
| `port` | API 监听端口;开发值为 `9150`。 |
| `dsn` | PostgreSQL 连接串。 |
| `storage_dir` | 服务端文件存储根目录。 |
| `max_upload_bytes` | multipart 请求体大小上限;开发值为 32 MiB。 |
| `auth_secret` | 邀请和登录会话签名密钥。 |
| `system_ai_key` | 可选的系统级 AI provider fallback key。 |
| `ai_key_encryption_secret` | 用户 AI key 的静态加密密钥。 |
| `allowed_origins` | 允许访问 API 的 Web/Tauri 来源列表。 |
不要提交生产数据库连接串、AI key、会话凭据或真实密钥。开发配置中的固定值和 Compose 数据库账号仅供本地使用,生产环境必须全部替换。修改 Web 来源或端口时,应同步更新 `allowed_origins`,否则浏览器会拦截跨域请求。
`go run ./cmd/seed` 还支持 `DATABASE_DSN``DATABASE_URL` 临时覆盖数据库地址,以及 `SENLIN_SEED_EMAIL``SENLIN_SEED_NAME``SENLIN_SEED_PASSWORD` 覆盖演示用户信息。
## API v1 概览
业务接口前缀为 `/api/v1`JSON 字段使用 camelCase对外 ID 使用 UUIDv7 字符串,时间使用 UTC RFC 3339。除连接状态和登录外接口都要求有效的 `Authorization: Bearer` 会话凭据。
| 方法 | 路径 | 成功响应 |
| --- | --- | --- |
| `GET` | `/api/v1/status` | `200`,包含 `timestamp` 的对象;无需登录。 |
| `POST` | `/api/v1/auth/login` | `200`,包含签名且会过期的 `token` 字段;请求体为 `email``password`。 |
| `GET` | `/api/v1/projects` | `200`,项目 DTO 数组。 |
| `POST` | `/api/v1/projects` | `201`,项目 DTO。 |
| `GET` | `/api/v1/projects/:projectId` | `200`,项目 DTO。 |
| `PATCH` | `/api/v1/projects/:projectId` | `200`,更新后的项目 DTO。 |
| `GET` | `/api/v1/projects/:projectId/workspace` | `200`聚合项目、频道、标签、Inbox、任务、AI 会话、笔记资料和计划任务的工作区 DTO。 |
| `POST` | `/api/v1/projects/:projectId/tasks` | `201`,任务 DTO。 |
| `PATCH` | `/api/v1/projects/:projectId/tasks/:taskId` | `200`,更新后的任务 DTO。 |
| `GET` | `/api/v1/projects/:projectId/tags` | `200`,该项目的标签 DTO 数组。 |
| `POST` | `/api/v1/projects/:projectId/tags` | `201`,标签 DTO。 |
| `POST` | `/api/v1/projects/:projectId/sources` | `201`,文件资料 DTO请求为含 `file` 和可选 `title` 的 multipart 表单。 |
| `POST` | `/api/v1/projects/:projectId/cron-plans` | `201`,计划任务 DTO只管理元数据不执行自主 Agent。 |
| `POST` | `/api/v1/projects/:projectId/inbox` | `201`Inbox 条目 DTO。 |
| `POST` | `/api/v1/inbox/:inboxId/analyze` | `200``suggestions` 草稿数组,不创建正式对象。 |
| `POST` | `/api/v1/inbox/:inboxId/confirm` | `200`,含 `createdCount`;只确认服务端已保存且由用户选中的建议。 |
| `GET` | `/api/v1/search?q=...` | `200``items` 数组,当前检索项目、任务和笔记。 |
| `GET` | `/api/v1/projects/:projectId/ai-sessions` | `200`AI 会话 DTO 数组。 |
| `POST` | `/api/v1/projects/:projectId/ai-sessions` | `201`AI 会话 DTO请求体只接收 `title``context`。 |
错误统一返回 `{"error":{"code":"...","message":"..."}}`。路径中的项目、任务和 Inbox ID 必须是 UUIDv7数据库自增 ID 不对外暴露。
## 验证
后端:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'backend')
go test ./...
```
Web
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'apps/web_v1')
node scripts/visual-check.mjs
npm run build
npm run lint
```
如果设置了指向隔离测试库的 `DATABASE_URL`,再运行 PostgreSQL 集成检查:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'backend')
go test -tags integration ./internal/models -run TestPostgresPing -v
```
不得把真实测试数据库凭据写入仓库。当前机器的逐项执行结果与产物路径见 [MVP 验证说明](docs/mvp-verification.md)。
## 桌面端
先完成 Web 依赖安装,再构建 Tauri 可执行文件:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'apps/desktop')
npm ci
npm run build
```
`npm run build` 会先执行 Web 生产构建,再运行 `tauri build --no-bundle`。Windows 产物位于 `apps/desktop/src-tauri/target/release/senlinai_workbench.exe`
需要安装包时运行:
```powershell
$repoRoot = (git rev-parse --show-toplevel).Trim()
Set-Location (Join-Path $repoRoot 'apps/desktop')
npm run bundle
```
打包需要 Rust stable、平台编译工具链和对应安装器依赖它与无安装包的可执行文件构建是两个独立验证项。
## 常见问题
### 数据库连接或认证失败
确认 Docker Desktop 和 Compose 服务正在运行,并用 `docker compose -f infra/docker-compose.yml ps` 查看状态。若本机已有 PostgreSQL 占用 `5432`,请停止冲突服务或同步修改 Compose 映射与 `backend/etc/agent.dev.yaml` 中的 `dsn`。演示数据和 API 必须连接到同一个数据库。
### 浏览器提示无法连接或 CORS 错误
先访问 `http://localhost:9150/api/v1/status`。如果 API 可达但浏览器仍失败,检查登录页的服务器地址、协议和端口,并把实际 Web 来源加入 `allowed_origins` 后重启 API。
### Vite 端口被占用
默认端口是 `5173`。可以停止占用进程,或让 Vite 选择可用端口;使用其他端口时必须同步配置后端 `allowed_origins`
### 演示账号无法登录
先成功运行 `go run ./cmd/seed`,再使用 seed 命令输出所对应的开发账号。若通过环境变量覆盖过演示用户信息,应使用覆盖后的值。生产环境不得使用默认演示密码。
### AI 会话返回缺少密钥或限流错误
创建 AI 会话前会执行每用户、每动作限流并选择加密存储的用户 key 或系统 fallback key。缺少可用 key 时返回服务不可用,超过配额时返回 `429`;不要在前端或提交记录中粘贴 key。
## 安全说明
- 登录会话使用签名且会过期的 bearer token服务端从认证中间件读取当前用户不接受可伪造的用户 ID 字符串。
- 用户 AI key 加密存储。AI 操作先限流,再选择 provider/key并记录 provider、key 类型、action、status 和 error日志不得记录 key 明文。
- AI 分析和会话不会自动创建正式任务、笔记或资料。Inbox 只有在用户确认服务端保存的建议后才创建对象,并保留来源 Inbox ID。
- 项目标签只在项目内有效。任务移动、标签写入和文件上传都校验项目所有权。
- 任务分享遵循最小可见范围:被指派人只能看到任务以及被显式分享的关联对象;分享的 note/source 必须与任务属于同一项目。
- 文件存储路径只由文件服务构造,上传在写磁盘前校验所有权和请求体大小。
- 生产部署必须替换所有开发凭据和密钥、限制 CORS 来源、使用独立数据库与受控存储目录,并通过 HTTPS 暴露服务。