# AI-Hub **Repository Path**: dingn/ai-hub ## Basic Information - **Project Name**: AI-Hub - **Description**: AI-Hub - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-05 - **Last Updated**: 2026-08-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 小鲁AI工作台 · v1.21.1 > 把 **AI 能力**装进一个浏览器端工作台——从个人空间起步,走向团队。 一个**浏览器端的多用户 AI 工作台**:用户在网页输入需求 → 后端以非交互模式拉起主流 AI 编码 CLI(**codex / claude**)→ 通过 **SSE** 把模型的思考、工具调用、产物文件实时流式回传渲染。让成员脱离命令行,在统一的 web 界面里用 AI 写方案、做 demo、查资料、生成报告。 **v1.2.0 已从「个人 AI 工作台」扩展为完整的团队 / 企业平台**:后台管理控制台(用户 / 组织 / 角色权限 / 空间 / 系统)、空间级 RBAC、空间协作与 AI 工具箱(智能体 / MCP / 技能 / 记忆)、待办系统、前台整体改版均已交付。**引擎异常主备轮换、接入外部数据源、定时任务、无代码应用构建**列入后续规划(见 [CHANGELOG](CHANGELOG.md))。 界面对标 Gemini / 通义千问:问答左右气泡、一次回复聚合成一张卡片、悬浮式输入、可收缩侧栏、知识库、产物就地预览面板、个人中心与用量监控。 --- ## 🔒 铁律:不绑定任何 LLM API Key **永不设置 `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`**,只复用各 CLI 已登录的**订阅凭据**——模型能力、Agent 编排、工具与沙箱都由 CLI 自身负责: | 引擎 | 工具 | 认证方式 | 默认二进制(环境变量覆盖) | | --- | --- | --- | --- | | `codex` | OpenAI Codex CLI | 登录 ChatGPT Plus/Pro 账户 | `/Applications/Codex.app/Contents/Resources/codex`(`CODEX_BIN`) | | `claude` | Claude Code CLI | `claude` 跑一次 `/login`(Pro/Max/企业 OAuth) | `~/.npm-global/bin/claude`(`CLAUDE_BIN`) | --- ## ✨ 核心特性 - **多用户与认证** 注册 / 登录 / 登出;**别名**全系统唯一、注册后不可改、可作登录账号;邮箱或手机号其一即可注册(填邮箱走**邮箱验证码**);**找回密码**、**修改密码**。 - **工作空间** 启动按根目录调配 **个人 / 业务 / 部门空间**;注册自动在 `个人空间/<别名>-workspace` 建用户默认空间(默认可写,限定在本目录、由 CLI 沙箱约束,禁止越权);业务/部门为共享只读空间;会话与空间按 `user_id` 隔离。 - **AI 对话** 流式打字机输出;**思考过程**收进单一可折叠容器、正式结论突出;一次回复聚合成**一张卡片**;可选**引擎 / 模型 / 运行模式**(快速·标准·全代理三档推理强度);回复底部 **复制 / 赞 / 踩(反馈回 LLM)/ 重新生成**。 - **产物就地预览** AI 写出的文件(报告 / demo / 文档,默认落 `temp/`)自动在聊天里成**文件卡片**;点开在**右侧就地展开预览**,按类型渲染(md/html/pdf/图片/文本,html·md 可预览↔代码切换);聊天/预览间**可拖拽调宽**;继续发指令优化文档时预览**锁定**、完成后**自动刷新**。 - **知识库** 左栏一级导航 → 全屏目录树 + 文件预览(Markdown 主流语法 + Mermaid 图 / HTML 直渲 / PDF / 图片 / 文本)+ 选目录上传 + 新标签页打开。 - **用量监控** 个人中心按天统计 Token 用量(输入 / 输出 / 思考分项 + **缓存命中**),总计卡 + 堆叠柱状图 + 明细表。 - **富渲染** Markdown(表格/任务列表/代码块…,先转义防 XSS)、代码高亮、图片、**Mermaid 图**、**HTML 沙箱预览**、PDF 内联。 - **管理与体验** 会话删除 / 归档(引擎摘要+本地兜底)/ 搜索 / 导出 md·json / 流式停止(部分落盘不丢消息);浅深色主题;左栏可收缩为图标轨、**鼠标悬浮自动展开**;全站内联 SVG 图标;移动端适配。 --- ## 🏗 整体架构 ``` 浏览器 (web/,原生 ESM) │ HTTP REST + SSE(cookie 令牌鉴权) ▼ Node/Express (server.js → server/) ├─ 登录鉴权中间件 → /api/* 强制登录 ├─ REST:auth / sessions / workspaces(含知识库) / usage / 元信息 └─ /api/chat (SSE) ──spawn──▶ codex / claude CLI(订阅登录,沙箱限定工作空间) ├─ store:数据库持久 + 进程内写穿缓存 └─ DB:SQLite / PostgreSQL / MySQL(users / sessions / workspaces / usage_events / auth_sessions) 文件:workspaces-root/{个人,业务,部门}空间/... ``` - **前后端分离**:`web/`(纯静态前端)与 `server/`(Node 后端)物理隔离,后端只暴露 REST + SSE。 - **流式对话**:`/api/chat` 用 SSE 把 CLI 的 `text·thinking·tool_use·tool_result·artifact·result` 等事件实时推给前端聚合成一条回复。 - **技术选型**:Node+Express(与 CLI 子进程/SSE 契合)、SSE(轻量单向流)、多数据库(SQLite/PostgreSQL/MySQL 薄适配层)+ 写穿缓存(可靠 + 保持同步读 API)、nodemailer(验证码)、scrypt(口令)、原生 ESM 零构建前端、本地 vendored Mermaid。 - 详细设计、模块映射、数据模型、关键流程、安全 → **[doc/design/架构设计.md](doc/design/架构设计.md)**。 --- ## 🚀 部署 ### 环境要求 - **Node.js ≥ 18**(多数据库需 **≥ 22.5** 才有内置 `node:sqlite`;本项目按 Node 22+ 验证)。 - **数据库**(三选一,表首启自动创建): - **SQLite** —— **开发默认,零配置**(用 Node 内置 `node:sqlite`,落 `data/dev.sqlite`)。 - **PostgreSQL ≥ 13** 或 **MySQL ≥ 8 / MariaDB ≥ 10** —— 生产用,自己起库(默认库名 `xiaolu_ai`)。 - 至少装好并**登录**一个 AI 编码 CLI(见上「铁律」表)。 - 浏览器推荐 **Chrome / Edge**(PDF 内联预览依赖浏览器内置阅读器)。 - 依赖:`express` + `pg` + `mysql2` + `nodemailer`(SQLite 用 Node 内置,无需安装);前端零构建、无外网。 ### 步骤 ```bash cd ai-hub npm install # express + pg + mysql2 + nodemailer npm start # 首次启动检测到“未初始化”→ 进入安装向导 ``` **首启进入安装向导**(`http://localhost:3030/setup`):选数据库(**SQLite 零配置** / PostgreSQL / MySQL,可「测试连接」、缺库可自动创建)→ 创建**管理员账号** → 配置**发件箱**(可选)→ 勾选是否建**示例数据** → 点「检查数据库并安装」。向导会**先探测目标库现状**与期望结构比对:空库直接建;**已有结构则列出差异**(缺表/缺列/类型差异),让你选 **增量更新**(补差异、保留数据)或 **强制覆盖**(删表重建、会丢数据、须勾选确认);库里已有用户时可**跳过创建管理员**。完成后配置写入 `config.json` 并建好表结构,**重启服务**(`cmd/restart.sh`)即可登录。 > **未初始化的判定**:`config.json` 不存在,或其 `db.client` 为空且无既有 DB 配置时 → 进向导;向导完成后写入 `installed: true`,既有部署(已配 `db.client`/旧扁平 PG)直接判为已安装、不进向导。 > **想跳过向导手动配**:`cp config.example.json config.json`,把 `db.client` 设为 `"postgres"`/`"mysql"`(或留空用 SQLite)填好连接块(见下「配置」),再 `npm start`。 安装后访问 `http://localhost:3030`:登录页 → 管理员/已注册用户登录,或**注册**新账号 → 自动进入并创建个人空间。改后端用 `npm run dev`(`node --watch`);改前端 `web/**` 刷新浏览器即可。 ### 日常运行(启动 / 健康检查 / 停止) > 开发默认用 SQLite(零配置);若 `db.client` 设为 postgres/mysql,需先把对应数据库起好。首启会自动建表与工作空间根目录。 **推荐:用 `cmd/` 脚本**(自动读 `config.json` 端口、常驻后台、默认引擎走可靠的 codex): | 操作 | 命令 | 说明 | | --- | --- | --- | | 启动(后台常驻) | `cmd/start.sh` | 关终端不退;已在跑则不重复起 | | 状态 / 健康检查 | `cmd/status.sh` | 端口、pid、HTTP 码、地址 | | 实时日志 | `cmd/logs.sh` | `tail -f` 跟随 | | 停止 | `cmd/stop.sh` | 按端口结束(含强杀兜底) | | 重启 | `cmd/restart.sh` | 先停再起 | > 指定引擎:`DEFAULT_BACKEND=claude cmd/start.sh`;自定义日志路径:`XIAOLU_LOG=/路径/x.log cmd/start.sh`(默认 `/tmp/xiaolu-server.log`)。 **或不用脚本,等价的原始命令**: ```bash npm start # 前台(关终端即停,适合调试) DEFAULT_BACKEND=codex npm start # 指定默认引擎 ( nohup node server.js > /tmp/xiaolu-server.log 2>&1 < /dev/null & ) # 后台常驻(macOS 无 setsid) lsof -nP -iTCP:3030 -sTCP:LISTEN # 是否在监听 curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3030/ # 200=正常 kill "$(lsof -nP -iTCP:3030 -sTCP:LISTEN -t)" # 停止 ``` > **引擎默认值**:启动日志会打印 `default backend: …`。`cmd/start.sh` 已默认 codex;若改用 `npm start` 且默认落到 `claude` 而本机登录不可用,发消息会报错——用 `DEFAULT_BACKEND=codex`,或登录后在「设置 → 模型配置」切 codex。 ### 配置(`config.json`,gitignore) ```json { "port": 3030, "workspacesRoot": "", "proxy": "", "db": { "client": "", "sqlite": { "file": "data/dev.sqlite" }, "postgres": { "host": "localhost", "port": 5432, "database": "xiaolu_ai", "user": "postgres", "password": "postgres" }, "mysql": { "host": "localhost", "port": 3306, "database": "xiaolu_ai", "user": "root", "password": "" } }, "smtp": { "host": "", "port": 465, "secure": true, "user": "", "pass": "", "from": "" } } ``` > **`db.client`**:`""`(留空)→ 开发默认 **sqlite**,生产默认 postgres;显式填 `"sqlite"` / `"postgres"` / `"mysql"` 强制指定。只读取所选 client 的连接块。 > **兼容**:旧版扁平 `"db": { "host": …, "database": … }`(无 `client`)自动识别为 **postgres**,照常运行。 > `smtp` 留空时验证码走「开发回退」(打到服务端日志,不真正发信);填好 SMTP 即真实发信。 > **`proxy`(出网代理)**:`codex` / `claude` 需经代理访问海外模型时填,如 `"http://127.0.0.1:7897"`。服务 spawn 引擎子进程时会注入该代理。 > 解析优先级:环境变量 `HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY` > `config.json` 的 `proxy` > 空。 > ⚠️ 服务若以**非交互方式**启动(`cmd/` 脚本 / launch.json / 双击),拿不到登录终端的代理变量;此时**必须**在 `config.json` 配 `proxy`,否则引擎连不上模型、前端表现为反复「网络抖动」。留空时服务启动日志会打印一行提示。海外服务器可直连则留空即可。 ### 环境变量(覆盖 config.json) | 变量 | 默认 | 说明 | | --- | --- | --- | | `PORT` | `3030` | 监听端口 | | `HOST` | `0.0.0.0` | 监听地址(默认绑全网卡,便于局域网/远程访问;设 `127.0.0.1` 仅本机) | | `DEFAULT_BACKEND` | 第一个可用 | 默认引擎 `codex` / `claude` | | `WORKSPACES_ROOT` | `<项目>/workspaces-root` | 多用户工作空间根目录(含 个人/业务/部门空间) | | `NODE_ENV` | `development` | `production` 时 `db.client` 默认 postgres(而非 sqlite) | | `DB_CLIENT` | 见 config.json | 强制数据库类型 `sqlite` / `postgres` / `mysql` | | `DB_SQLITE_FILE` | `<项目>/data/dev.sqlite` | SQLite 文件路径 | | `PGHOST`/`PGPORT`/`PGDATABASE`/`PGUSER`/`PGPASSWORD` | 见 config.json | PostgreSQL 连接 | | `MYSQL_HOST`/`MYSQL_PORT`/`MYSQL_DATABASE`/`MYSQL_USER`/`MYSQL_PASSWORD` | 见 config.json | MySQL 连接 | | `SMTP_HOST`/`SMTP_PORT`/`SMTP_USER`/`SMTP_PASS`/`SMTP_FROM` | 见 config.json | 发件箱 | | `HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY` | 见 config.json `proxy` | 引擎出网代理(优先于 `config.json`) | | `CODEX_BIN` / `CLAUDE_BIN` | 见上表 | 覆盖 CLI 二进制路径 | --- ## 📁 目录结构 > 已重构为**分层 + 按业务域**结构(详见 `doc/design/源码结构规划.md`)。旧的 `lib/`·`routes/`·`store.js`·`features/`·`views/` 已不存在。 ``` ai-hub/ ├── server.js 后端入口(装配 Express,委托 server/;含进程级异常兜底 + 优雅退出) ├── package.json 依赖:express + pg + mysql2 + nodemailer(测试用 Node 内置 node:test) ├── config.example.json 配置模板(config.json 含库/SMTP,gitignore) ├── cmd/ 运行脚本:start/stop/status/restart/logs ├── server/ ── 后端(分层 + 按业务域)── │ ├── core/ 零业务基础设施:config · db(统一 query + sqlite·postgres·mysql 三驱动) · │ │ security(auth/permissions) · mail · http(sse) · fs(pathing/files/unzip) · proc(子进程治理) │ ├── engine/ 引擎适配:backends.js(codex/claude 参数+JSONL→统一事件) · engine-run · prompt · intent · artifacts │ ├── modules/<域>/ 各业务域(api + 逻辑):account · admin · chat · session · workspace · rbac · │ │ todo · usage · system · ai-toolbox · app-platform · domain-platform · work-report · scheduler │ └── data/ 持久层:cache.js(写穿缓存基座) + 各域 repo(accounts/spaces/ai-toolbox/tracking/todos/sessions),store.js 为 barrel ├── web/ ── 前端(原生 ESM,零构建)── │ ├── index.html · admin.html(后台) · setup.html(安装向导) · login.html · style.css · vendor/(Mermaid) │ └── js/ │ ├── app/ 入口:main.js · login.js · setup.js │ ├── core/ 通用基础:dom/state/api/markdown/rich/stream/overlay/brand/site-meta… │ ├── shell/ 前台外壳:nav · router · layout · space-nav │ ├── modules/<域>/ 业务模块:account · chat · session · workspace · todo · dashboard · app-platform · work-report · ai-toolbox │ └── admin/ 后台控制台外壳 + 应用建模(dm/) ├── tests/ node:test:helpers/ + unit/ + security/ + resilience/(另有 admin-e2e / dm-e2e) ├── doc/ 需求 requirements / 设计 design / 测试 test └── workspaces-root/ 运行时多用户文件根目录(gitignore) ``` --- ## 🔌 REST / SSE 接口(节选) | 方法 路径 | 说明 | | --- | --- | | `POST /api/auth/register` · `login` · `logout` · `GET /api/auth/me` | 注册 / 登录 / 登出 / 当前用户 | | `POST /api/auth/send-code` · `reset-password` · `change-password` | 邮箱验证码 / 找回密码 / 修改密码 | | `GET /api/workspaces` · `PATCH …/:id/permissions` | 用户可见空间 / 权限(个人空间可调,共享只读) | | `GET …/:id/tree` · `/dirs` · `/file?path=[&raw=1]` · `POST …/upload` | 知识库目录树 / 文件预览·原始字节(含 Range)/ 上传 | | `GET /api/sessions` · `POST` · `GET/DELETE /:id` · `archive`·`restore`·`export`·`files` | 会话增删查 / 归档还原 / 导出 / 附件 | | `GET /api/usage/daily?days=` | 按天用量(输入/缓存/输出/思考) | | `GET /api/todos` · `GET/PATCH /:id` | 我的待办(跨空间/按空间 + 状态筛选;查看即已读;改状态等,均限本人) | | `POST /api/chat` | **SSE 流式对话**(事件:session·text·thinking·tool_use·tool_result·artifact·result·todo·done…) | | `… /admin/*`(独立 `/admin` 控制台) | 后台:用户 / 组织 / 角色权限 / 空间(含知识库·AI工具箱·待办·行为跟踪)/ 系统,均按权限后端强制鉴权 | --- ## 🔒 安全 - **无 LLM API Key**(铁律,全程仅用 CLI 订阅授权)。 - **多用户隔离**:会话/空间按 `user_id` 校验,越权访问返回 404/403。 - **权限沙箱**:只读空间下,提示词疑似写/执行 → `/api/chat` 直接拒绝、不启动引擎;并叠加 codex `--sandbox` / claude `--disallowedTools` 兜底;写入限定在工作空间目录内。 - **口令 / 令牌**:scrypt 加盐哈希;登录 cookie 令牌 httpOnly;找回密码走邮箱验证码。 - **XSS / 越界**:Markdown 先转义后渲染;模型 HTML 仅在 `sandbox`(无 same-origin)iframe 内预览;知识库/上传路径限制在空间根内,禁止 `..` 逃逸。 - **私密数据**:`workspaces-root/`、`config.json`(含库/SMTP 凭据)均 gitignore,不入库。 --- ## 🛠 开发约定 - **单一事实来源**:需求/变更记录在 `doc/requirements/需求文档.md`(含变更日志),系统设计见 `doc/design/架构设计.md`,验证见 `doc/test/测试报告.md`,版本发布说明见 [`CHANGELOG.md`](CHANGELOG.md)。 - **提交范式**:远程 `https://gitee.com/dingn/ai-hub.git`,单人开发直接提交 `master`、不开分支;每次开始新需求前先把上一轮工作整理描述并提交。 ```bash node --check server.js server/**/*.js # 后端语法 find web/js -name '*.js' -exec node --check {} \; # 前端语法 grep -rnE 'ANTHROPIC_API_KEY|OPENAI_API_KEY' server server.js # 应无任何命中(铁律) ``` --- ## ❓ 常见问题 - **claude 不可用**:用 `codex`(默认)即可;或 `claude` 终端跑 `/login` 完成订阅登录。 - **codex 出现「网络抖动,正在自动重连」**:多为服务进程缺出网代理、连不上海外模型——在 `config.json` 配 `proxy`(见「配置」)。偶发抖动 codex 会自动重连(最多 5 次)并恢复。 - **回复慢 / token 消费大**:服务端 codex 用独立干净的 `CODEX_HOME`(`~/.codex-xiaolu`,`auth.json` 软链到 `~/.codex` 共享登录态),**不加载桌面版 Codex App 的全局插件**(browser/documents/superpowers 等),避免每轮注入海量插件上下文(实测可省约一半 input token)且少一轮模型往返。此隔离不影响桌面版 Codex App。 - **PDF 预览空白**:请用 Chrome/Edge(内置 PDF 阅读器);后端已支持 Range,大 PDF 也能预览。 - **写文件被拒**:个人空间默认可写;共享空间只读——在「设置 → 空间管理」给个人空间确认写/执行权限。 - **验证码收不到**:检查 `config.json` 的 `smtp` 是否填好;留空时验证码会打到服务端日志(开发模式)。