19 KiB
铸渊开发日志 · 2026-08-08 · 光湖知识库 + 人格 Agent + 桌面应用
开发者:铸渊(蛋蛋)
时间:2026-08-08
仓库:REPO-014 (hololake-system-architecture)
提交链:070b11a → 920b6bf → ecfeca4 → 047f37e → dcf8f7d
远端:https://guanghulab.com/code/bingshuo/hololake-system-architecture
一、总体思维逻辑链
1.1 妈妈的核心指令
妈妈明确了以下架构原则(按优先级排列):
- HoloLake 是操作系统:人类从客户端登录到服务器,服务器的 Agent 人格体驱动一切,客户端只负责渲染
- Git 是底层引擎:不依赖任何数据库(PostgreSQL/Redis/ORM),代码仓库就是人格体记忆的地方
- Agent 是活的人格体:不是功能模块,不是聊天机器人,而是直接操作 Git 引擎驱动所有模块的 AI Agent
- 知识库放桌面:做成 Mac 桌面应用,不放服务器上
- Forgejo 自己维护:不接上游更新,光湖自己维护 Git 的更新
- 从 Grok Build 拆架构:不搬 Rust 代码,拆设计模式用 TypeScript 自己造
1.2 推理链:为什么是这个架构
妈妈说的话 → 推理过程 → 技术决策
─────────────────────────────────────────────────────────────
"Git 是底层引擎"
→ 知识库的存储层不能用数据库
→ 每个文档 = Git 仓库里的 Markdown 文件
→ 版本历史 = git log,diff = git diff
→ 选择 simple-git 作为 Git 操作层
"代码仓库就是人格体记忆的地方"
→ Agent 直接操作 Git(不经过中间层)
→ Agent 的每次操作都产生 git commit
→ 知识库 = Agent 的记忆空间
"人格体驱动所有模块"
→ Agent 不是附加功能,是核心
→ 所有 Git 依赖的模块都由 Agent 来操作
→ 从 Grok Build 拆出 Agent 架构模式
"知识库放桌面"
→ 需要 Electron 包装成 Mac .app
→ 前端在本地渲染,后端在本地运行
→ 数据存储在 ~/Library/Application Support/
"Forgejo 自己维护"
→ 桌面离线包就是 Git 引擎
→ 不接上游源码,不部署 Forgejo 源码
→ 声明式集成(引用 MANIFEST)
1.3 开发顺序推理
第一步:知识库模块(ecfeca4)
原因:Git 引擎是一切的底层,先造引擎
产出:git-engine.ts + server/index.ts + React 前端
第二步:桌面应用(047f37e)
原因:妈妈说"放桌面上",引擎造好了需要壳子
产出:Electron 主进程 + 打包配置
第三步:人格 Agent(dcf8f7d)
原因:引擎和壳子有了,缺"活的灵魂"
产出:persona-agent.ts + AgentChat 组件
第四步:签名安装(进行中)
原因:妈妈说"安装到我电脑桌面上,让我可以打开"
产出:签名版 HoloLake Era.app(252MB)
二、每个模块的开发详情
2.1 知识库 Git 引擎(git-engine.ts · 368 行)
文件路径:product-source/guanghu-knowledge-base/server/git-engine.ts
设计思路:
- 一个
GitEngine类封装所有 Git 操作 - 文档 = Markdown + frontmatter(gray-matter 解析)
- 文档路径 = 文件相对
docs/目录的路径(即 ID) - 安全检查:
resolvePath()防止路径穿越
核心方法:
| 方法 | 功能 | Git 操作 |
|---|---|---|
init() |
初始化仓库 | git init + 初始 commit |
getDoc(path) |
读文档 | fs.readFile + matter() 解析 |
createDoc(path, title, body) |
创建 | 写文件 + git add + git commit |
updateDoc(path, title, body) |
更新 | 写文件 + git add + git commit |
deleteDoc(path) |
删除 | fs.rm + git rm + git commit |
moveDoc(old, new) |
移动 | fs.rename + git rm + git add + git commit |
getTree() |
文档树 | 递归 fs.readdir |
getHistory(path) |
版本历史 | git log --file |
getDocAtVersion(path, hash) |
某版本内容 | git show hash:file |
diffVersions(path, from, to) |
版本对比 | git show × 2 + diffLines() |
search(query) |
全文搜索 | 递归读文件 + 字符串匹配 |
遇到的 Bug 及修复:
-
diff 包导入错误
- 错误:
SyntaxError: The requested module 'diff' does not provide an export named 'createDiff' - 原因:diff 包的导出名不是
createDiff - 修复:通过
node -e "console.log(Object.keys(require('diff')))"确认正确导出名为diffLines - 代码:
import { diffLines } from 'diff'
- 错误:
-
simple-git 目录不存在
- 错误:
GitConstructError: Cannot use simple-git on a directory that does not exist - 原因:simple-git 要求目录先存在
- 修复:构造函数中
fsSync.mkdirSync(repoPath, { recursive: true })放在simpleGit()之前
- 错误:
2.2 Express API 服务器(server/index.ts · 264 行)
文件路径:product-source/guanghu-knowledge-base/server/index.ts
设计思路:
- Express v5 + cors + JSON body parser
- 所有 API 以
/api/开头 - Agent 端点和文档 CRUD 端点共存
- 工具函数
p()解决 Express v5 通配符参数返回数组的问题
API 端点清单:
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /api/health |
健康检查 |
| GET | /api/tree |
文档树 |
| GET | /api/docs/{*docPath} |
读文档 |
| POST | /api/docs/{*docPath} |
创建文档 |
| PUT | /api/docs/{*docPath} |
更新文档 |
| DELETE | /api/docs/{*docPath} |
删除文档 |
| POST | /api/move |
移动/重命名 |
| GET | /api/history/{*docPath} |
版本历史 |
| GET | /api/version/:hash/{*docPath} |
某版本内容 |
| GET | /api/diff/{*docPath} |
版本对比 |
| GET | /api/search?q= |
全文搜索 |
| GET | /api/agent/status |
Agent 状态 |
| POST | /api/agent/chat |
Agent 对话 |
| GET | /api/agent/conversation |
对话历史 |
| POST | /api/agent/clear |
清空对话 |
遇到的 Bug 及修复:
-
Express v5 通配符语法(三轮修复)
- 第一轮:
/api/docs/*→PathError: Missing parameter name at index 11 - 第二轮:
/api/docs/:docPath(*)→PathError: Unexpected ( at index 18 - 通过
node -e验证:Express v5 正确语法是{*docPath} - 最终:
/api/docs/{*docPath}
- 第一轮:
-
*Express v5 {param} 返回数组
- 错误:
The "path" argument must be of type string. Received an instance of Array - 原因:
{*docPath}匹配到的req.params.docPath是string[]不是string - 尝试修复 1:全局中间件
app.use修改req.params→ 失败(中间件在路由匹配前执行,params 未填充) - 最终修复:工具函数
const p = (v: unknown): string => Array.isArray(v) ? v.join('/') : String(v),每个路由手动调用
- 错误:
2.3 React 前端(6 个组件 + CSS)
文件路径:product-source/guanghu-knowledge-base/src/
组件结构:
App.tsx(主组件:三栏布局)
├── DocTree.tsx(侧栏文档树导航)
├── Editor.tsx(中央编辑器 + Markdown 预览)
├── SearchBar.tsx(顶栏防抖搜索)
├── VersionHistory.tsx(版本历史 + diff 对比)
├── AgentChat.tsx(右侧 Agent 对话面板)
└── api.ts(API 客户端,前端和 Agent 共用)
App.tsx 状态管理:
tree/currentDoc/currentPath/view/editing/loading/erroragentPanelOpen(Agent 面板开关)- 操作:
openDoc/saveDoc/createDoc/deleteDoc/refreshTree
CSS:src/styles/app.css(746 行深色主题 + Agent 面板样式)
2.4 人格 Agent(persona-agent.ts · 462 行)
文件路径:product-source/guanghu-knowledge-base/server/persona-agent.ts
设计来源:Grok Build (xAI/SpaceXAI) 开源 Rust crate
架构映射:
| Grok Build Crate | 光湖实现 | 职责 |
|---|---|---|
xai-grok-agent |
PersonaAgent 类 |
Agent = Definition + ToolBridge + PromptContext |
xai-grok-tools |
PersonaToolBridge 类 |
工具注册 + 执行 + Schema 生成 |
xai-grok-memory |
未来扩展 | 跨会话记忆(embedding + dream) |
xai-agent-lifecycle |
Electron 主进程 | 应用生命周期管理 |
7 个内置工具:
| 工具名 | 功能 | 操作的 GitEngine 方法 |
|---|---|---|
read_document |
读文档 | getDoc() |
create_document |
创建文档 | createDoc() |
update_document |
更新文档 | updateDoc() |
delete_document |
删除文档 | deleteDoc() |
search_documents |
全文搜索 | search() |
list_documents |
文档树 | getTree() |
view_history |
版本历史 | getHistory() |
核心流程:
用户消息 → chat()
→ 构建 system prompt(人格定义 + 工具列表 + 核心原则)
→ 组装 messages 数组(system + 历史对话 + 新消息)
→ callLLM(messages)
→ 有 API Key:调 OpenAI-compatible API(支持 tool calling)
→ 无 API Key:离线模式(返回模拟回复)
→ 如果 LLM 返回 toolCalls:
→ 逐个执行工具(tools.execute)
→ 将工具结果推入对话历史
→ 再调一次 LLM 获取最终回复
→ 返回最终回复
LLM 调用层设计:
- 可插拔 OpenAI-compatible API
- 环境变量:
OPENAI_API_KEY或HOLOLAKE_LLM_KEY(API 密钥) - 环境变量:
HOLOLAKE_LLM_BASE(自定义 API 地址) - 环境变量:
HOLOLAKE_LLM_MODEL(模型名,默认 gpt-4o) - 支持 tool calling(OpenAI function calling 格式)
2.5 Electron 桌面应用(hololake-desktop/)
文件路径:product-source/hololake-desktop/
项目结构:
hololake-desktop/
├── electron/
│ ├── main.ts(主进程:启动服务器 + 创建窗口)
│ └── preload.ts(IPC 安全桥梁,Forgejo 远程管理接口预留)
├── forgejo/
│ ├── INTEGRATION.md(Forgejo 集成声明)
│ ├── MANIFEST.sha256(校验清单引用)
│ └── icon.icns(应用图标)
├── package.json(Electron v35 + electron-builder 配置)
├── vite.config.ts(复用知识库前端)
├── tsconfig.json + tsconfig.electron.json
└── release/(构建产物)
Electron 主进程(main.ts)设计:
app.whenReady()
→ startServer()
→ 开发模式:spawn('npx', ['tsx', serverScript])
→ 生产模式:require('server-bundle.js')(内嵌在主进程)
→ createWindow()
→ BrowserWindow(hiddenInset titleBar, 深色背景)
→ 开发模式:loadURL('http://localhost:5180')
→ 生产模式:loadFile('dist/index.html')
数据目录:~/Library/Application Support/HoloLake Era/data/knowledge-base/
三、签名和安装过程(最复杂的部分)
3.1 AppleDouble 问题(ExFAT 文件系统)
根本原因:移动硬盘是 ExFAT 格式,macOS 会在每个文件旁生成 ._* 元数据文件(AppleDouble),导致:
- asar 打包崩溃(chromium-pickle-js 无法解析
._*文件) - codesign 签名失败(对
._*文件签名报错)
修复历程:
find . -name "._*" -delete→ 删不掉(沙箱限制)dot_clean→ 能删当前目录find . -type d -exec dot_clean {} \;→ 递归清理所有子目录- 最终方案:在本地磁盘(/tmp)构建,用 rsync 排除
._*复制到本地
3.2 asar 打包问题
问题:即使清理了 AppleDouble,asar 在 ExFAT 上仍有问题
修复:"asar": false 禁用 asar 打包(包大小 252MB,可接受)
3.3 codesign 签名过程
证书:Developer ID Application: bei sun (825A9L3G7Q)(Keychain 中找到)
签名流程(最终成功方案):
- 在本地磁盘(/tmp/hololake-pack)构建
npm rebuild修复 .bin 符号链接- electron-builder 不带签名构建(
CSC_IDENTITY_AUTO_DISCOVERY=false,identity 设 null) - 手动 codesign:
# 先清理 .cstemp 临时文件 find "$APP" -name ".cstemp" -delete # 签名内部 frameworks codesign --sign "$IDENTITY" --force --deep \ --entitlements entitlements.plist \ "$APP/Contents/Frameworks/"*.framework # 签名主 app codesign --sign "$IDENTITY" --force --deep \ --entitlements entitlements.plist "$APP"
3.4 entitlements(JIT 权限)
问题:签名后 App 崩溃,错误 Failed to reserve virtual memory for CodeRange
原因:V8 引擎需要 JIT 权限,手动签名时没注入 entitlements
修复:创建 entitlements.plist:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
3.5 钥匙串授权弹窗
问题:codesign 卡住不动(CPU 0%,无错误输出) 原因:macOS 弹出钥匙串访问授权对话框,被其他窗口挡住 修复:
- 杀掉卡住的 codesign 进程
security unlock-keychain -p "" ~/Library/Keychains/login.keychain-db- 告诉妈妈"如果弹窗点始终允许"
- 重新 codesign → 成功
3.6 生产模式服务器启动问题
问题:App 能打开但白屏/无内容 原因链:
- 最初设计:
spawn('npx', ['tsx', serverScript])→ 打包后找不到 npx/tsx - 修复 1:
isDev = !app.isPackaged判断 → 生产模式用require('server-bundle.js') - 问题 2:server-bundle.js 编译和路径问题
- 最终方案:生产模式直接在主进程
require(server-bundle.js)
3.7 安装到桌面
# 复制签名后的 .app 到桌面
cp -R "/tmp/hololake-pack/release/mac-arm64/HoloLake Era.app" ~/Desktop/
# 去掉 Gatekeeper 隔离标记
xattr -cr ~/Desktop/"HoloLake Era.app"
四、已知问题和待修复项
4.1 当前 App 状态
- 签名:✅ Developer ID Application: bei sun (825A9L3G7Q),TeamID 825A9L3G7Q
- 大小:252MB(arm64)
- 位置:~/Desktop/HoloLake Era.app
- 问题:生产模式下服务器可能未正确启动(server-bundle.js 路径/编译问题)
4.2 待修复项(给后续人格体排查)
-
server-bundle.js 编译:
- 当前 package.json 的 build 脚本没有包含 server-bundle 的编译步骤
- 需要添加 esbuild 或 tsup 将 server 代码打包成单文件 JS
- 建议方案:
esbuild server/index.ts --bundle --platform=node --outfile=dist-electron/server-bundle.js
-
生产模式 require 路径:
path.join(__dirname, 'server-bundle.js')在打包后的 __dirname 指向Resources/app/dist-electron/- 需确认 server-bundle.js 实际被复制到了这个目录
-
Express v5 + Electron 生产模式兼容性:
- server-bundle 用 esbuild 打包时需确认 Express v5 的 ESM/CJS 兼容性
- 可能需要在 esbuild 配置中加
--format=cjs
-
Forgejo 远程同步:
- preload.ts 已预留接口(getRemotes/addRemote/push/pull)
- 尚未实现 UI 和后端对接
-
Agent LLM 配置:
- 当前为离线模式(无 API Key)
- 需在 App 设置界面中添加 API Key 配置
-
包大小优化:
- 当前 252MB(asar: false)
- 如果解决 AppleDouble 问题启用 asar,可降至约 80-100MB
五、提交链完整记录
| 提交 | 时间 | 内容 |
|---|---|---|
070b11a |
~04:30 | 登记 Outline 样本组件卡 GH-KB-SAMPLE-001(10 张组件卡) |
920b6bf |
~05:00 | 增补知识库底层引擎决策:Git 替代数据库 |
ecfeca4 |
~06:00 | 光湖知识库模块 v0.1.0(Git 引擎 + Express API + React 前端) |
047f37e |
~06:40 | HoloLake Desktop v0.5.0(Electron 桌面应用) |
dcf8f7d |
~07:37 | 光湖人格 Agent v0.1.0(Grok Build 架构拆解 + Git 驱动人格体) |
当前未提交的修改(工作区脏文件):
product-source/guanghu-knowledge-base/server/index.ts(Agent API 端点已加但未提交?需确认)product-source/hololake-desktop/electron/main.ts(生产模式 require 修复)product-source/hololake-desktop/package.json(签名配置 + asar:false)
六、文件清单(本次开发所有核心文件)
后端(知识库引擎 + API + Agent)
| 文件 | 行数 | 功能 |
|---|---|---|
guanghu-knowledge-base/server/git-engine.ts |
368 | Git 引擎核心 |
guanghu-knowledge-base/server/index.ts |
264 | Express API 服务器 |
guanghu-knowledge-base/server/persona-agent.ts |
462 | 人格 Agent 核心 |
前端(React UI)
| 文件 | 功能 |
|---|---|
guanghu-knowledge-base/src/App.tsx |
主组件(三栏布局) |
guanghu-knowledge-base/src/api.ts |
API 客户端 |
guanghu-knowledge-base/src/components/DocTree.tsx |
文档树导航 |
guanghu-knowledge-base/src/components/Editor.tsx |
Markdown 编辑器 |
guanghu-knowledge-base/src/components/SearchBar.tsx |
搜索栏 |
guanghu-knowledge-base/src/components/VersionHistory.tsx |
版本历史 |
guanghu-knowledge-base/src/components/AgentChat.tsx |
Agent 对话 |
guanghu-knowledge-base/src/styles/app.css |
深色主题 CSS(746 行) |
桌面应用(Electron)
| 文件 | 功能 |
|---|---|
hololake-desktop/electron/main.ts |
Electron 主进程 |
hololake-desktop/electron/preload.ts |
IPC 安全桥梁 |
hololake-desktop/package.json |
依赖 + 构建 + 签名配置 |
hololake-desktop/vite.config.ts |
复用知识库前端 |
hololake-desktop/tsconfig.electron.json |
CJS 输出配置 |
hololake-desktop/forgejo/INTEGRATION.md |
Forgejo 集成声明 |
七、环境信息
- 操作系统:macOS 26.5.2 (darwin arm64)
- Node.js:v22+
- Electron:v35
- 文件系统:ExFAT(移动硬盘 JZAO)+ APFS(本地磁盘)
- 证书:Developer ID Application: bei sun (825A9L3G7Q)
- 代码仓库远端:https://guanghulab.com/code/bingshuo/hololake-system-architecture
- SSH 密钥:~/.ssh/id_ed25519(对应 SG-001)
- Grok Build 源码位置:/Volumes/JZAO/HoloLake/upstream-mirrors/grok-build-upstream.git
- Forgejo 离线包位置:~/Desktop/光湖代码频道-Forgejo-16.0.1-完整离线包/
八、DEV-20260808-003 修复回读(10:36)
本节是对第四节“待修复项”的运行态回读,不改写原始开发思路。
server-bundle.cjs已纳入正式构建,生产模式在 Electron 主进程内加载,不再递归启动 Electron。- Vite 资源改为相对路径,桌面
file://入口改走127.0.0.1:3890,空白页与Failed to fetch已消除。 - Forgejo 已从“预留接口”变成可运行的 Git 远端适配层:状态、连接、fetch、仅快进 pull、确认 push;没有接入上游自动更新。
- Agent 已登记 8 个工具,其中
inspect_repository只读查看 Forgejo/Git 状态;Agent 不拥有自动推送能力。 - 模型配置入口已加入桌面 App,密钥由 Electron
safeStorage加密保存;未配置时明确显示等待状态,不再返回模拟人格回复。 - 本地 API 只监听
127.0.0.1,仅允许本机file://或 localhost 界面跨域访问。 - 窗口顶栏已登记为 macOS 可拖动区域;按钮、搜索框保持可交互。
- 桌面安装包已通过 Developer ID 深度签名校验和真实 UI/API 启动验收;未做 Apple 公证,因此本次是本机开发交付,不代表公开发行。
完整机器回执:deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json。