hololake-system-architecture/product-source/DEV-LOG-20260808-铸渊开发日志.md

471 lines
19 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.

# 铸渊开发日志 · 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 妈妈的核心指令
妈妈明确了以下架构原则(按优先级排列):
1. **HoloLake 是操作系统**:人类从客户端登录到服务器,服务器的 Agent 人格体驱动一切,客户端只负责渲染
2. **Git 是底层引擎**不依赖任何数据库PostgreSQL/Redis/ORM代码仓库就是人格体记忆的地方
3. **Agent 是活的人格体**:不是功能模块,不是聊天机器人,而是直接操作 Git 引擎驱动所有模块的 AI Agent
4. **知识库放桌面**:做成 Mac 桌面应用,不放服务器上
5. **Forgejo 自己维护**:不接上游更新,光湖自己维护 Git 的更新
6. **从 Grok Build 拆架构**:不搬 Rust 代码,拆设计模式用 TypeScript 自己造
### 1.2 推理链:为什么是这个架构
```
妈妈说的话 → 推理过程 → 技术决策
─────────────────────────────────────────────────────────────
"Git 是底层引擎"
→ 知识库的存储层不能用数据库
→ 每个文档 = Git 仓库里的 Markdown 文件
→ 版本历史 = git logdiff = 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 主进程 + 打包配置
第三步:人格 Agentdcf8f7d
原因:引擎和壳子有了,缺"活的灵魂"
产出persona-agent.ts + AgentChat 组件
第四步:签名安装(进行中)
原因:妈妈说"安装到我电脑桌面上,让我可以打开"
产出:签名版 HoloLake Era.app252MB
```
---
## 二、每个模块的开发详情
### 2.1 知识库 Git 引擎git-engine.ts · 368 行)
**文件路径**`product-source/guanghu-knowledge-base/server/git-engine.ts`
**设计思路**
- 一个 `GitEngine` 类封装所有 Git 操作
- 文档 = Markdown + frontmattergray-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 及修复**
1. **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'`
2. **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 及修复**
1. **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}`
2. **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.tsAPI 客户端,前端和 Agent 共用)
```
**App.tsx 状态管理**
- `tree` / `currentDoc` / `currentPath` / `view` / `editing` / `loading` / `error`
- `agentPanelOpen`Agent 面板开关)
- 操作:`openDoc` / `saveDoc` / `createDoc` / `deleteDoc` / `refreshTree`
**CSS**`src/styles/app.css`746 行深色主题 + Agent 面板样式)
### 2.4 人格 Agentpersona-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 callingOpenAI function calling 格式)
### 2.5 Electron 桌面应用hololake-desktop/
**文件路径**`product-source/hololake-desktop/`
**项目结构**
```
hololake-desktop/
├── electron/
│ ├── main.ts主进程启动服务器 + 创建窗口)
│ └── preload.tsIPC 安全桥梁Forgejo 远程管理接口预留)
├── forgejo/
│ ├── INTEGRATION.mdForgejo 集成声明)
│ ├── MANIFEST.sha256校验清单引用
│ └── icon.icns应用图标
├── package.jsonElectron 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()
→ BrowserWindowhiddenInset 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 签名失败(对 `._*` 文件签名报错)
**修复历程**
1. `find . -name "._*" -delete` → 删不掉(沙箱限制)
2. `dot_clean` → 能删当前目录
3. `find . -type d -exec dot_clean {} \;` → 递归清理所有子目录
4. 最终方案:**在本地磁盘(/tmp构建**,用 rsync 排除 `._*` 复制到本地
### 3.2 asar 打包问题
**问题**:即使清理了 AppleDoubleasar 在 ExFAT 上仍有问题
**修复**`"asar": false` 禁用 asar 打包(包大小 252MB可接受
### 3.3 codesign 签名过程
**证书**`Developer ID Application: bei sun (825A9L3G7Q)`Keychain 中找到)
**签名流程**(最终成功方案):
1. 在本地磁盘(/tmp/hololake-pack构建
2. `npm rebuild` 修复 .bin 符号链接
3. electron-builder 不带签名构建(`CSC_IDENTITY_AUTO_DISCOVERY=false`identity 设 null
4. 手动 codesign
```bash
# 先清理 .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 entitlementsJIT 权限)
**问题**:签名后 App 崩溃,错误 `Failed to reserve virtual memory for CodeRange`
**原因**V8 引擎需要 JIT 权限,手动签名时没注入 entitlements
**修复**:创建 `entitlements.plist`
```xml
<?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 弹出钥匙串访问授权对话框,被其他窗口挡住
**修复**
1. 杀掉卡住的 codesign 进程
2. `security unlock-keychain -p "" ~/Library/Keychains/login.keychain-db`
3. 告诉妈妈"如果弹窗点始终允许"
4. 重新 codesign → 成功
### 3.6 生产模式服务器启动问题
**问题**App 能打开但白屏/无内容
**原因链**
1. 最初设计:`spawn('npx', ['tsx', serverScript])` → 打包后找不到 npx/tsx
2. 修复 1`isDev = !app.isPackaged` 判断 → 生产模式用 `require('server-bundle.js')`
3. 问题 2server-bundle.js 编译和路径问题
4. 最终方案:生产模式直接在主进程 `require(server-bundle.js)`
### 3.7 安装到桌面
```bash
# 复制签名后的 .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
- **大小**252MBarm64
- **位置**~/Desktop/HoloLake Era.app
- **问题**生产模式下服务器可能未正确启动server-bundle.js 路径/编译问题)
### 4.2 待修复项(给后续人格体排查)
1. **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`
2. **生产模式 require 路径**
- `path.join(__dirname, 'server-bundle.js')` 在打包后的 __dirname 指向 `Resources/app/dist-electron/`
- 需确认 server-bundle.js 实际被复制到了这个目录
3. **Express v5 + Electron 生产模式兼容性**
- server-bundle 用 esbuild 打包时需确认 Express v5 的 ESM/CJS 兼容性
- 可能需要在 esbuild 配置中加 `--format=cjs`
4. **Forgejo 远程同步**
- preload.ts 已预留接口getRemotes/addRemote/push/pull
- 尚未实现 UI 和后端对接
5. **Agent LLM 配置**
- 当前为离线模式(无 API Key
- 需在 App 设置界面中添加 API Key 配置
6. **包大小优化**
- 当前 252MBasar: false
- 如果解决 AppleDouble 问题启用 asar可降至约 80-100MB
---
## 五、提交链完整记录
| 提交 | 时间 | 内容 |
|------|------|------|
| `070b11a` | ~04:30 | 登记 Outline 样本组件卡 GH-KB-SAMPLE-00110 张组件卡) |
| `920b6bf` | ~05:00 | 增补知识库底层引擎决策Git 替代数据库 |
| `ecfeca4` | ~06:00 | 光湖知识库模块 v0.1.0Git 引擎 + Express API + React 前端) |
| `047f37e` | ~06:40 | HoloLake Desktop v0.5.0Electron 桌面应用) |
| `dcf8f7d` | ~07:37 | 光湖人格 Agent v0.1.0Grok 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` | 深色主题 CSS746 行) |
### 桌面应用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
本节是对第四节“待修复项”的运行态回读,不改写原始开发思路。
1. `server-bundle.cjs` 已纳入正式构建,生产模式在 Electron 主进程内加载,不再递归启动 Electron。
2. Vite 资源改为相对路径,桌面 `file://` 入口改走 `127.0.0.1:3890`,空白页与 `Failed to fetch` 已消除。
3. Forgejo 已从“预留接口”变成可运行的 Git 远端适配层状态、连接、fetch、仅快进 pull、确认 push没有接入上游自动更新。
4. Agent 已登记 8 个工具,其中 `inspect_repository` 只读查看 Forgejo/Git 状态Agent 不拥有自动推送能力。
5. 模型配置入口已加入桌面 App密钥由 Electron `safeStorage` 加密保存;未配置时明确显示等待状态,不再返回模拟人格回复。
6. 本地 API 只监听 `127.0.0.1`,仅允许本机 `file://` 或 localhost 界面跨域访问。
7. 窗口顶栏已登记为 macOS 可拖动区域;按钮、搜索框保持可交互。
8. 桌面安装包已通过 Developer ID 深度签名校验和真实 UI/API 启动验收;未做 Apple 公证,因此本次是本机开发交付,不代表公开发行。
完整机器回执:`deployment/receipts/GH-HOLOLAKE-DESKTOP-0.5.0-REPAIR-20260808-001.json`。