森林AI
产品定位
森林AI 是一个以项目为中心、面向私有化部署的工作台 MVP,服务于个人知识工作者、团队负责人和可信的内部用户。它把项目、任务、Inbox 收集、Markdown 笔记、文件资料、AI 会话、项目内标签和轻量任务分发组织在同一工作区中。
Web 客户端桌面优先,同时保留移动浏览器可用性;登录页允许输入私有部署服务器的 IP 地址或域名。
MVP 范围
当前版本包含:
- 项目创建、设置和聚合工作区。
- 项目内任务、标签、文件资料和计划任务元数据。
- Inbox 收集、分析建议和用户确认创建对象的流程。
- 项目、任务和笔记的关键词搜索。
- 项目内 AI 会话入口、密钥选择、限流与调用审计。
- React Web 客户端和 Tauri 桌面壳。
当前版本不包含实时即时通讯、项目级成员角色体系、匿名公开分享、自主 Agent 执行、语义或向量搜索、第三方数据源集成、原生移动 App、浏览器扩展、离线编辑或本地优先同步。
技术栈
- 后端:Go 1.26.1、Gin、Gorm、PostgreSQL 16。
- Web:React 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;其他版本应满足各锁文件与工具链要求。
目录结构
.
├── 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
在仓库根目录运行:
docker compose -f infra/docker-compose.yml up -d
Compose 只用于本地开发,创建 PostgreSQL 16 服务并监听 localhost:5432。其中的默认数据库凭据不得用于生产环境。
3. 初始化演示数据
Set-Location backend
go run ./cmd/seed
默认演示账号为 demo@senlin.ai,默认密码为 password123。它们只用于本地开发;生产部署必须创建正式用户并替换所有默认凭据与密钥。
4. 启动 API
在新的终端中运行:
Set-Location backend
go run ./cmd/api
开发配置默认监听 http://localhost:9150。可用 GET /healthz 检查进程健康状态;Web 登录页使用 GET /api/v1/status 检查服务器连接。
5. 启动 Web 客户端
在新的终端中运行:
Set-Location apps/web_v1
npm ci
npm run dev
Vite 默认地址为 http://localhost:5173。登录时服务器地址填写 http://localhost:9150;也可以通过 VITE_API_BASE_URL 指定 Web 的初始 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 不对外暴露。
验证
后端:
Set-Location backend
go test ./...
Web:
Set-Location apps/web_v1
node scripts/visual-check.mjs
npm run build
npm run lint
如果设置了指向隔离测试库的 DATABASE_URL,再运行 PostgreSQL 集成检查:
Set-Location backend
go test -tags integration ./internal/models -run TestPostgresPing -v
不得把真实测试数据库凭据写入仓库。当前机器的逐项执行结果与产物路径见 MVP 验证说明。
桌面端
先完成 Web 依赖安装,再构建 Tauri 可执行文件:
Set-Location 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。
需要安装包时运行:
Set-Location 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 暴露服务。