# 调试与测试

<cite>
**本文引用的文件**
- [package.json](file://package.json)
- [next.config.ts](file://next.config.ts)
- [electron/main.ts](file://electron/main.ts)
- [electron/preload.ts](file://electron/preload.ts)
- [scripts/build-electron.mjs](file://scripts/build-electron.mjs)
- [src/app/api/agents/route.ts](file://src/app/api/agents/route.ts)
- [src/lib/db.ts](file://src/lib/db.ts)
- [src/lib/sdk/message-mapper.ts](file://src/lib/sdk/message-mapper.ts)
- [src/lib/sdk/permission-bridge.ts](file://src/lib/sdk/permission-bridge.ts)
- [src/lib/mcp-test.ts](file://src/lib/mcp-test.ts)
- [src/lib/im/bridge-manager.ts](file://src/lib/im/bridge-manager.ts)
- [src/lib/im/delivery.ts](file://src/lib/im/delivery.ts)
- [src/lib/im/adapters/discord.ts](file://src/lib/im/adapters/discord.ts)
- [src/lib/im/adapters/base.ts](file://src/lib/im/adapters/base.ts)
- [src/lib/im/im-events.ts](file://src/lib/im/im-events.ts)
- [src/components/layout/app-layout.tsx](file://src/components/layout/app-layout.tsx)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本指南面向Forge项目的开发者与测试工程师，系统性地说明如何在本地进行开发调试（Electron主进程、渲染进程、API路由）、日志系统的使用与配置、单元与集成测试的编写方法、性能分析工具的使用（内存泄漏检测与性能瓶颈定位）、常见问题的调试技巧与错误排查流程，并给出自动化测试与持续集成的配置建议。

## 项目结构
Forge采用“Next.js应用 + Electron打包”的双层架构：前端以Next.js构建，生产环境通过独立服务器运行；Electron负责启动本地服务并在桌面窗口中加载该服务器内容。开发时通过脚本同时启动Next.js开发服务器与Electron主进程，实现热更新与桌面端联调。

```mermaid
graph TB
Dev["开发者终端<br/>pnpm dev"] --> NextDev["Next.js 开发服务器<br/>localhost:3000"]
Dev --> ElectronMain["Electron 主进程<br/>electron/main.ts"]
ElectronMain --> Preload["预加载脚本<br/>electron/preload.ts"]
ElectronMain --> LocalServer["本地独立服务器<br/>.next/standalone"]
NextDev --> UI["Next.js 前端页面"]
LocalServer --> API["Next.js API 路由"]
UI --> |"IPC 调用"| Preload
Preload --> |"注册 IPC 处理器"| ElectronMain
ElectronMain --> |"打开窗口加载"| LocalServer
```

图表来源
- [package.json:13-25](file://package.json#L13-L25)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

章节来源
- [package.json:13-25](file://package.json#L13-L25)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

## 核心组件
- Electron主进程：负责启动本地独立服务器、创建窗口、注册IPC处理器、文件系统监听、剪贴板与系统路径操作等。
- 预加载脚本：通过contextBridge向渲染进程暴露安全的API桥接。
- Next.js独立服务器：生产模式下由Electron子进程运行，提供API路由与静态资源。
- 数据库与迁移：基于better-sqlite3，集中初始化表结构、迁移逻辑与种子数据。
- IM桥接层：消息分片、重试、去重、适配器抽象、事件发布订阅与SSE同步。
- 工具与SDK：消息映射、权限桥接、MCP连接测试等。

章节来源
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [src/lib/db.ts:18-437](file://src/lib/db.ts#L18-L437)
- [src/lib/im/im-events.ts:1-33](file://src/lib/im/im-events.ts#L1-L33)

## 架构总览
下面的序列图展示开发调试时的关键交互：开发者执行“pnpm dev”后，Next.js开发服务器与Electron主进程并行启动；Electron主进程在开发模式下直接加载localhost:3000；渲染进程通过预加载脚本调用IPC接口；API路由处理请求并与数据库交互。

```mermaid
sequenceDiagram
participant Dev as "开发者"
participant N as "Next.js 开发服务器"
participant E as "Electron 主进程"
participant P as "预加载脚本"
participant R as "渲染进程"
Dev->>N : 启动开发服务器
Dev->>E : 启动 Electron 主进程
E->>E : 注册 IPC 处理器
E->>N : 在开发模式下加载 http : //localhost : 3000
E->>R : 创建窗口并加载 URL
R->>P : 调用 exposed API
P->>E : IPC 调用 (如 fs : watch)
E-->>P : 返回结果
R->>N : 发起 API 请求 (Next.js 路由)
N-->>R : 返回响应
```

图表来源
- [package.json:13-25](file://package.json#L13-L25)
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/app/api/agents/route.ts:1-42](file://src/app/api/agents/route.ts#L1-L42)

## 详细组件分析

### Electron 主进程调试
- 启动方式
  - 开发：使用“pnpm dev”并行启动Next.js与Electron；Electron在开发模式下直接加载localhost:3000。
  - 生产：Electron启动独立服务器进程，使用打包的.node-runtime与剥离后的.standalone目录。
- 关键调试点
  - 服务器启动与健康检查：主进程会等待独立服务器就绪再创建窗口；若失败弹出错误框并退出。
  - 子进程输出：独立服务器stdout/stderr会被转发到主进程控制台，便于定位问题。
  - 文件系统监听：IPC处理器支持目录监听与防抖通知，注意忽略规则与异常捕获。
  - 资源路径与PATH扩展：为保证SDK可执行程序可用，主进程会扩展PATH，需关注平台差异。
- 断点与日志
  - 在主进程入口处设置断点，观察独立服务器启动、端口分配、窗口创建与IPC注册。
  - 利用控制台输出定位“[server]”前缀日志，确认独立服务器状态。

章节来源
- [package.json:13-25](file://package.json#L13-L25)
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)

### 渲染进程调试
- API桥接
  - 预加载脚本通过contextBridge暴露安全API，渲染进程通过window.electronAPI访问。
  - 常用能力：目录选择、文件系统监听回调、剪贴板读写、数据目录查询、系统路径打开。
- 断点与日志
  - 在渲染侧调用预加载API前后设置断点，验证IPC往返与返回值。
  - 使用浏览器开发者工具的网络面板查看Next.js API请求与响应。
- 实时事件
  - 应用布局组件通过EventSource订阅“/api/im-events”，建立一次性的SSE连接用于IM桥接实时同步，注意连接生命周期与重连策略。

章节来源
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/components/layout/app-layout.tsx:187-196](file://src/components/layout/app-layout.tsx#L187-L196)

### API路由调试
- Next.js API路由位于src/app/api下，采用App Router约定式路由。
- 示例：agents路由提供代理列表查询与新增，内部使用SQLite数据库访问。
- 调试要点
  - 使用浏览器或curl/postman直接访问路由，观察SQL查询与JSON响应。
  - 在路由函数内设置断点，检查请求体解析、参数校验与数据库事务。
  - 关注跨域与CORS问题（开发环境默认localhost:3000）。

章节来源
- [src/app/api/agents/route.ts:1-42](file://src/app/api/agents/route.ts#L1-L42)
- [src/lib/db.ts:18-437](file://src/lib/db.ts#L18-L437)

### 日志系统与配置
- 控制台日志
  - Electron主进程：独立服务器的stdout/stderr统一打印“[server]”前缀，便于区分。
  - IM桥接层：重连尝试与电路 breaker触发会记录日志，便于定位链路异常。
  - SDK工具：工具结果与错误会输出特定标签的日志，便于快速定位问题。
- 日志策略建议
  - 按模块划分：主进程、渲染进程、API路由、IM桥接、SDK工具。
  - 级别管理：Info/Debug/Warn/Error，避免生产环境过多Debug噪声。
  - 结构化输出：统一时间戳、模块名、线程/进程标识，便于日志聚合与检索。
- 配置位置
  - Next.js独立服务器：通过独立打包与环境变量控制日志级别。
  - Electron主进程：通过子进程env传递NODE_ENV与自定义日志开关。

章节来源
- [electron/main.ts:120-135](file://electron/main.ts#L120-L135)
- [src/lib/im/bridge-manager.ts:569-592](file://src/lib/im/bridge-manager.ts#L569-L592)
- [src/lib/sdk/message-mapper.ts:542-560](file://src/lib/sdk/message-mapper.ts#L542-L560)

### 单元测试与集成测试
- 测试框架选择
  - 建议使用Vitest（与当前生态一致）或Jest，结合@testing-library/react进行UI测试。
  - 对于API路由，可使用supertest或直接调用Next.js测试工具。
- 测试用例设计
  - 主进程：模拟IPC调用、文件系统监听、错误分支（如无法启动独立服务器）。
  - 渲染进程：模拟预加载API调用、SSE连接、错误提示与回退逻辑。
  - API路由：覆盖GET/POST/PUT/DELETE，边界条件（空输入、非法ID、并发写入）。
  - IM桥接：消息分片、重试、去重、适配器抽象、事件发布订阅。
  - 工具与SDK：MCP连接测试、权限审计清理、消息映射与错误处理。
- 数据库测试
  - 使用better-sqlite3内存数据库或临时文件，确保迁移逻辑与种子数据正确。
  - 验证外键约束、索引与事务一致性。

章节来源
- [src/lib/db.ts:18-437](file://src/lib/db.ts#L18-L437)
- [src/lib/mcp-test.ts:1-50](file://src/lib/mcp-test.ts#L1-L50)
- [src/lib/sdk/permission-bridge.ts:224-261](file://src/lib/sdk/permission-bridge.ts#L224-L261)
- [src/lib/sdk/message-mapper.ts:542-560](file://src/lib/sdk/message-mapper.ts#L542-L560)

### 性能分析与内存泄漏检测
- 内存泄漏检测
  - 使用Chrome DevTools Memory快照对比，关注长驻对象（SSE连接、事件监听器、适配器实例、缓存集合）。
  - 特别关注IM桥接中的队列、等待器、活动会话映射与权限允许映射，确保在组件卸载或会话结束时清理。
- 性能瓶颈分析
  - 使用Chrome Profiler录制渲染进程CPU热点，优化重渲染与事件处理。
  - 使用Network面板分析API路由延迟与SSE连接耗时。
  - 使用Node.js内置profiler分析主进程与独立服务器的CPU占用。
- 优化建议
  - 减少不必要的全局状态与大对象持有。
  - 对高频事件（文件系统变更）采用防抖/节流。
  - 合理关闭子进程与清理定时器、监听器与缓存。

章节来源
- [src/lib/sdk/permission-bridge.ts:224-261](file://src/lib/sdk/permission-bridge.ts#L224-L261)
- [src/lib/im/delivery.ts:223-240](file://src/lib/im/delivery.ts#L223-L240)
- [src/lib/im/adapters/discord.ts:83-128](file://src/lib/im/adapters/discord.ts#L83-L128)

### IM桥接与SSE同步
- 组件职责
  - BridgeManager：适配器生命周期管理、指数退避重连、电路 breaker、状态机。
  - Delivery：消息分片、重试与去重，保障平台消息有序投递。
  - Adapters：抽象消费/发送接口，具体实现（Discord/TG等）。
  - IM Events：发布订阅机制，供SSE端点与渲染侧使用。
- 调试要点
  - 观察重连次数与延迟，确认电路 breaker触发阈值合理。
  - 检查消息分片长度与换行分割策略，避免平台限制导致失败。
  - 确认SSE连接建立与断线重连，渲染侧EventSource生命周期管理。

```mermaid
classDiagram
class BridgeManager {
+startAdapter(channelId)
+reconnect(channelId)
-exponentialBackoff(attempt)
+setState(channelId, status, reason)
}
class Delivery {
+splitText(text, maxLen)
+retryWithBackoff(fn, maxRetries)
+dedupe(hash)
}
class AdapterBase {
<<abstract>>
+consumeOne(signal)
+send(msg)
+sendImage(chatId, buffer, caption)
+sendFile(chatId, buffer, filename, caption)
+sendTypingIndicator(chatId)
}
class DiscordAdapter {
+consumeOne(signal)
+send(msg)
+sendImage(...)
+sendFile(...)
+sendTypingIndicator(...)
}
class ImEvents {
+onImEvent(listener)
+emitImEvent(type, data)
}
BridgeManager --> AdapterBase : "管理适配器"
AdapterBase <|-- DiscordAdapter : "实现"
BridgeManager --> Delivery : "使用"
ImEvents --> BridgeManager : "事件发布"
```

图表来源
- [src/lib/im/bridge-manager.ts:569-592](file://src/lib/im/bridge-manager.ts#L569-L592)
- [src/lib/im/delivery.ts:203-244](file://src/lib/im/delivery.ts#L203-L244)
- [src/lib/im/adapters/base.ts:40-78](file://src/lib/im/adapters/base.ts#L40-L78)
- [src/lib/im/adapters/discord.ts:83-128](file://src/lib/im/adapters/discord.ts#L83-L128)
- [src/lib/im/im-events.ts:1-33](file://src/lib/im/im-events.ts#L1-L33)

## 依赖分析
- 构建与打包
  - Next.js独立打包与electron-builder配合，主进程与预加载脚本通过esbuild构建，独立服务器通过脚本处理符号链接、pnpm hoisting修复、路径剥离与Node运行时捆绑。
- 运行时依赖
  - better-sqlite3用于本地数据库；@larksuiteoapi/node-sdk作为外部包被独立打包时需要补齐依赖。
- 开发依赖
  - concurrently、wait-on用于并行启动与等待；electron、electron-builder用于桌面打包。

```mermaid
graph LR
P["package.json"] --> N["Next.js 独立打包"]
P --> E["Electron 打包"]
N --> S[".next/standalone"]
E --> D["dist-electron"]
S --> R["API 路由"]
D --> M["electron/main.ts"]
D --> L["electron/preload.ts"]
```

图表来源
- [package.json:13-25](file://package.json#L13-L25)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)

章节来源
- [package.json:13-25](file://package.json#L13-L25)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)

## 性能考虑
- 独立服务器与压缩
  - Next.js独立打包默认不启用gzip，避免缓冲SSE流；生产环境建议使用electron-builder进行打包。
- 依赖与原生模块
  - 打包阶段对better-sqlite3进行原生模块重建，确保与捆绑的Node版本兼容。
- 路径剥离
  - 将构建机绝对路径替换为/app，减少隐私泄露风险并保持一致性。
- IM桥接
  - 采用指数退避与抖动，防止风暴重试；消息分片与去重降低平台限流风险。

章节来源
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)
- [scripts/build-electron.mjs:157-202](file://scripts/build-electron.mjs#L157-L202)
- [src/lib/im/bridge-manager.ts:569-592](file://src/lib/im/bridge-manager.ts#L569-L592)

## 故障排查指南
- 无法启动独立服务器
  - 现象：Electron弹出错误框并退出。
  - 排查：检查主进程控制台“[server]”日志；确认独立服务器已就绪后再创建窗口；核对端口占用与PATH扩展。
- IPC调用无响应
  - 现象：渲染侧调用预加载API无返回。
  - 排查：确认预加载API已正确expose；检查IPC处理器注册；在主进程断点验证事件进入与返回。
- API路由异常
  - 现象：浏览器或curl返回错误。
  - 排查：在路由函数内断点，检查请求体、参数与数据库访问；查看better-sqlite3错误与迁移是否成功。
- IM桥接不稳定
  - 现象：消息丢失、重复或延迟。
  - 排查：检查重连次数与延迟；确认消息分片与去重逻辑；验证SSE连接与渲染侧EventSource生命周期。
- 权限与会话泄漏
  - 现象：内存缓慢增长。
  - 排查：定期调用会话清理函数；确认事件监听器与适配器实例释放；检查权限允许映射与活动时间记录。

章节来源
- [electron/main.ts:272-288](file://electron/main.ts#L272-L288)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/app/api/agents/route.ts:1-42](file://src/app/api/agents/route.ts#L1-L42)
- [src/lib/sdk/permission-bridge.ts:224-261](file://src/lib/sdk/permission-bridge.ts#L224-L261)
- [src/lib/im/bridge-manager.ts:569-592](file://src/lib/im/bridge-manager.ts#L569-L592)

## 结论
通过明确的调试流程、完善的日志策略、规范的测试用例与性能分析手段，可以高效定位并解决Forge在开发与生产环境中的各类问题。建议在CI中加入单元测试、集成测试与打包校验，确保每次提交的质量与稳定性。

## 附录
- 自动化测试与持续集成建议
  - 测试矩阵：多平台（macOS/Linux/Windows）与多Node版本（与捆绑版本一致）。
  - CI步骤：安装依赖、类型检查、单元测试、API路由测试、端到端场景（可选）、打包与签名（可选）。
  - 缓存：缓存node_modules与electron-builder缓存目录，提升构建速度。
  - 安全：对敏感信息使用CI密钥，避免硬编码。