Pi Plus 采用经典的 前后端分离 + 反向代理 架构,整体分为五层:浏览器客户端 → Nginx 入口 → Node 后端 → AI 智能体引擎 → 数据存储。各层职责清晰,通过 HTTP/HTTPS 与 SSE 事件流通信。
技术栈:Vite 6 + React 19 + TypeScript + Rolldown 构建。纯前端无桌面客户端。
角色:静态资源托管 + 反向代理 + SSL 终止 + gzip 压缩。
入口:/opt/pi-web-plus/backend/src/server.mjs(2589 行 ESM 模块)。运行方式:systemd pi-web-plus.service,Restart=always。
角色:智能体核心 — 模型管理、工具执行、会话生命周期、权限系统。
sessions/ — JSONL 格式,每行一条事件(message / toolCall / toolResult / compaction…)sessions-archive/ — 归档(软删除 / 压缩前备份)web-prefs.json — 按会话隔离的 Plan/权限/插话/工具配置web-queues.json — 消息队列磁盘持久化models.json — Provider 配置 + 模型列表(可读写)auth.json — API Key(原子写 · 权限 600 · 脱敏显示)settings/ — SDK 全局设置web-schedules.json — 定时任务push.json — 推送配置(Telegram/Bark)resumes/ — 429 续跑任务skills/ — 技能定义notebook.md — 跨会话笔记本/var/www/libs/ — 字体 / GitHub CSS / 第三方库/var/www/pi-design/ — /design 架构说明页/var/www/pi-share/ — /share/ 会话外链| 端口 | 协议 | 绑定 | 服务 | 进程/管理 | 说明 |
|---|---|---|---|---|---|
| 80 | HTTP | 0.0.0.0 | Nginx | nginx master | HTTP→HTTPS 301 跳转 |
| 443 | HTTPS | 0.0.0.0 | Nginx | nginx master/worker | SSL 终止 + 反代 + 托管 |
| 3067 | HTTP | 127.0.0.1 | Node(pi-web-plus) | systemd pi-web-plus.service | 后端 API,仅内网可达 |
| 8080 | HTTP | 127.0.0.1 | python3 | 独立进程 | 其他业务服务 |
| 8081 | HTTP | 127.0.0.1 | node(editor-server) | 独立进程 | 编辑器服务 |
| 8082 | HTTP | 127.0.0.1 | python3(ip服务) | 独立进程 | IP 查询服务 |
| 8088 | HTTP | 0.0.0.0 | Nginx | nginx worker | 看板/监控面板 |
| 9801 | HTTP | 127.0.0.1 | node(boat) | 独立进程 | 其他业务 |
activeSessionFile,其他会话的流式回合完全不受影响。createPermissionGate() 实例,策略(ask/allow/deny)按会话隔离。t:state/hello/mu/me/as/ae 等事件,前端按当前会话过滤。eventSeq 递增,每个事件带 eid,供 Last-Event-ID 对账。t:ver(含 build 版本),前端检测到版本变化自动软刷新。connectEvents()(sse.ts)使用指数退避(0.5s→16s),最多 6 次。models.json:{ providers: { "openrouter": { models: [...], baseUrl, api }, "deepseek": {...}, "bigmodel": {...} } }/api/config/models 读写,设置页可视化 CRUDauth.json:{ "provider": { type: "api_key", key: "..." } },原子写(临时文件 + rename),权限 600modelRuntime.getAvailable():SDK 层发现所有可用模型selectableModels() 只保留 openrouter/free 或 :free 后缀,防止 UI 误选付费模型/api/models 返回可选项;/api/config/models 返回含脱敏凭证的完整配置setProviderApiKey():先写运行时 → 再写 auth.json(原子写)listCredentialsMasked():只返回 provider + type + hasKey,不暴露 Key 值listAuthProviders():Fallback 从 auth.json 读 key 存在性setSessionModel() 用 muteMethod 拦截 SDK 的 setDefaultModelAndProvider 写全局操作,保证会话隔离currentState() 汇总所有 assistant 消息的 m.usage:input / output / cacheRead / cacheWrite / costgetSessionStats():SDK 层统计 userMessages / assistantMessages / toolCalls / toolResults / totalMessagestokenUsage 结构:{ input, output, cacheRead, cacheWrite, total, cost }getContextSafe() → session.getContextUsage():返回 { tokens, contextWindow, percent }compaction:压缩摘要信息(summary / tokensBefore / timestamp),缓存于 slot.compactionCacheinstallCompactionStreamBridge() 将 SDK 的 streamFunction 输出转成 t:ms/t:mu SSE 事件,让用户实时看到压缩进度(原为死代码)POST /api/share/session:提取会话中的 user/assistant 消息,生成纯 HTML 页面share-{randomBytes(6).hex}.html),防枚举/var/www/pi-share/,Nginx ^~ /share/ alias 托管POST /api/session/export?format=jsonl:调用 SDK exportToJsonl(),输出到 /tmp/pi-web-plus-exports/format=html:SDK exportToHtml()format=md:自实现 Markdown(用户/助手文本主干 + 工具调用折叠摘要)/api/session/export/file?name=session-xxx.{jsonl|md|html}(正则校验文件名防路径穿越)/api/files:列出文件(支持 showHidden 开关)/api/file:读取文本文件(限制 256KB,二进制拒绝)/api/file/download:流式下载(resolveSafe 防路径穿越)showHidden=1 参数,后端 listDir() 的 showHidden 参数控制是否显示点文件(.gitignore 始终显示)/api/browse:绝对目录浏览(带路径校验)createAuthToken(secret):生成 {id}.{exp}.{HMAC-SHA256签名},TTL 7天verifyAuthToken(token, secret):验证签名 + 过期时间,使用 timingSafeEqual 防时序攻击piweb_plus_token(HttpOnly · SameSite=Lax)PI_WEB_PASSWORD 环境变量(当前值已配置)createPermissionGate():每个 Slot 独立实例tool_call 事件 → emit t:perm SSE → 前端弹窗确认clearSessionAllows() 可清空resolveSafe() 检查 ..;archiveFileOf() 限制只在会话目录内sanitizeToolPairs() 清洗孤儿 toolResult / 落单 toolCall(防 OpenAI 兼容接口 400)| 功能 | 文件/位置 | 关键函数 |
|---|---|---|
| 后端入口 | backend/src/server.mjs | handleApi, broadcast, currentState, createSlot, bindSlot |
| 认证 | backend/src/lib/auth.mjs | createAuthToken, verifyAuthToken, extractAuthToken |
| 会话路由 | backend/src/routes/session.mjs | sessionRouter(/api/session/*, /api/events, /api/share/*) |
| 模型配置 | backend/src/lib/models-config.mjs | read/writeModelsFile, setProviderApiKey, listCredentialsMasked |
| 权限门禁 | backend/src/lib/permissions.mjs | createPermissionGate, DANGEROUS set |
| Plan 模式 | backend/src/lib/plan-mode.mjs | createPlanModeExtensionFactory, PLAN_MODE_PROMPT |
| /btw 侧问 | backend/src/lib/btw.mjs | runBtwChat, createBtwExtensionFactory |
| 文件安全 | backend/src/lib/fs-safe.mjs | resolveSafe, listDir, readTextFile, listAbsoluteDir |
| Git 操作 | backend/src/lib/git.mjs | gitSummary, gitDiff, gitBranches, gitTree, gitBlob |
| Web 偏好 | backend/src/lib/web-prefs.mjs | read/writeSessionPrefs, DEFAULT_WEB_PREFS |
| SSE 客户端 | frontend-next/src/sse.ts | connectEvents(EventSource + 指数退避) |
| 会话状态 | frontend-next/src/store/SessionProvider.tsx | SessionProvider(~700行核心状态管理) |
| 侧栏 | frontend-next/src/components/Sidebar.tsx | NewSessionBtn(Canvas 粒子动画), SessionRow |
| 工程面板 | frontend-next/src/components/Panel.tsx | FilesPane / GitPane / SkillsPane / ToolsPane / NotebookPane |
基于现有架构与使用场景,以下功能均可在前端 + 后端的现有扩展点上快速落地。工作量评估以「人·小时」为单位(假设 1 名熟悉技术栈的开发者)。
GET https://openrouter.ai/api/v1/usage,Bearer Key)/root/.pi/agent/usage.json,每日 cron 同步一次/api/usage/sync(手动/自动)和 /api/usage(查询)路由{provider: [{key, label, enabled, lastUsed, error}]}/api/config/credentials 支持数组读写;新增 /api/config/key/rotate 轮换接口/api/config/key/status 调用各 Provider 的 usage/health 端点/root/.pi/agent/shares.json,记录 { id, sessionFile, url, createdAt, views, title }GET /api/shares(列表)/ DELETE /api/shares/:id(撤销)/ POST /api/share/session(增强:登记到 shares.json)visualViewport resize,动态调整输入框位置http://host:11434,兼容 OpenAI 格式,几乎零改造/root/.pi/agent/audit/YYYY-MM-DD.jsonl,每日滚动/api/audit 路由(按时间范围/会话/工具类型过滤)| 优先级 | 功能 | 工作量 | ROI 评估 | 建议 |
|---|---|---|---|---|
| P0 | 免费模型额度统计 | ~8h | 高(直接省钱) | 立即执行 |
| P0 | 多 Key 轮换与额度 | ~12h | 高(可靠性保障) | 立即执行 |
| P1 | 会话分享管理后台 | ~7h | 中(管理便利) | 本周内 |
| P1 | 移动端深度优化 | ~16h | 中(用户体验) | 下周安排 |
| P2 | 更多模型源 | 2-12h/家 | 低(按需) | 有需求时 |
| P2 | 审计日志 | ~12h | 中(合规) | 团队有要求时 |
/opt/pi-web-plus/ 项目根目录(含 .git)/opt/pi-web-plus/backend/src/ 后端源码/opt/pi-web-plus/frontend-next/ 前端源码/opt/pi-web-plus/frontend-next/dist/ 构建产物(nginx 托管)/root/.pi/agent/ 数据目录(会话/models/auth/prefs/schedules)/etc/systemd/system/pi-web-plus.service 主服务/etc/systemd/system/pi-web-plus.service.d/override.conf 密码覆盖/etc/systemd/system/pi-web-plus.service.d/10-home.conf HOME 环境/usr/local/bin/piweb-redeploy.sh 部署脚本(软链接)/etc/nginx/conf.d/pi.haoaiganfan.top.conf 主站点/etc/nginx/conf.d/docs.haoaiganfan.top.conf 文档站点/etc/nginx/snippets/pi-web-plus-frontend.conf 前端共享片段/etc/nginx/snippets/haoaiganfan-ssl.conf SSL 片段/etc/nginx/snippets/errors.conf 错误页片段| 方法 | 路径 | 说明 | 鉴权 |
|---|---|---|---|
| POST | /api/login | 密码登录 → 返回 HMAC Token | 无需 |
| POST | /api/logout | 退出登录 | 需要 |
| GET | /api/health | 健康检查(ok/name/build/slots) | 无需 |
| GET | /api/me | 当前用户信息 | 需要 |
| GET | /api/events | SSE 事件流(Long-Poll) | 需要 |
| GET | /api/sessions | 会话列表 + 项目分组 | 需要 |
| GET | /api/sessions/search?q= | 全文搜索(grep 预过滤) | 需要 |
| POST | /api/new | 新建会话 | 需要 |
| POST | /api/switch | 切换会话 | 需要 |
| POST | /api/prompt | 发送消息(支持图片) | 需要 |
| POST | /api/abort | 中止当前回合 | 需要 |
| GET | /api/state | 会话状态(tail/full 模式) | 需要 |
| POST | /api/session/delete | 软删除(归档) | 需要 |
| POST | /api/session/rename | 重命名 | 需要 |
| POST | /api/session/fork | 分叉为新会话 | 需要 |
| POST | /api/session/compact | 压缩上下文 | 需要 |
| POST | /api/session/export | 导出 JSONL/HTML/MD | 需要 |
| POST | /api/share/session | 生成分享链接 | 需要 |
| GET | /api/models | 可用模型列表 | 需要 |
| POST | /api/model | 切换模型 | 需要 |
| GET | /api/config/models | 模型配置(含脱敏凭证) | 需要 |
| POST | /api/config/provider | 添加/更新 Provider | 需要 |
| POST | /api/config/credentials | 保存/删除 API Key | 需要 |
| GET | /api/tools | 工具列表 + 开关状态 | 需要 |
| POST | /api/tools | 设置活动工具 | 需要 |
| GET/POST | /api/plan | Plan 模式开关 | 需要 |
| GET/POST | /api/delivery | 插话策略设置 | 需要 |
| POST | /api/btw | /btw 临时侧问 | 需要 |
| GET | /api/push/config | 推送配置 | 需要 |
| GET | /api/schedules | 定时任务列表 | 需要 |
| GET | /api/files | 文件浏览(showHidden 开关) | 需要 |
| GET | /api/git | Git 状态/Diff/Branch | 需要 |
| GET | /api/skills | 技能列表 | 需要 |
| GET | /api/notebook | 跨会话笔记本 | 需要 |
本文档基于对 pi.haoaiganfan.top 部署环境(2026-09-15)的系统性分析整理,涵盖系统架构、实现原理与功能规划。
服务器:110.40.142.210(OpenCloudOS)· 框架:pi-web-plus v0.1.0 · 构建日期:2026-09-15
文档地址:https://docs.haoaiganfan.top/ · 本地路径:/var/www/pi-docs/index.html