# 服务器管理

<cite>
**本文引用的文件**
- [electron/main.ts](file://electron/main.ts)
- [next.config.ts](file://next.config.ts)
- [package.json](file://package.json)
- [scripts/build-electron.mjs](file://scripts/build-electron.mjs)
- [src/lib/forge-data.ts](file://src/lib/forge-data.ts)
- [src/app/api/workspaces/[id]/init/route.ts](file://src/app/api/workspaces/[id]/init/route.ts)
- [src/lib/mcp-test.ts](file://src/lib/mcp-test.ts)
- [README.md](file://README.md)
</cite>

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

## 简介
本文件聚焦于Electron主进程中的服务器管理功能，系统性解析Next.js独立服务器（standalone）在Electron中的启动流程、端口分配与进程管理策略；详述Node.js二进制查找逻辑、环境变量配置与PATH扩展机制；解释服务器生命周期、错误处理与优雅关闭；对比开发模式与生产模式差异、资源路径处理与跨平台兼容；并给出健康检查、超时与故障恢复策略，以及配置优化与性能监控建议。

## 项目结构
- Electron主进程入口位于 electron/main.ts，负责：
  - 开发模式下直接加载本地Next开发服务器（localhost:3000）
  - 生产模式下启动Next独立服务器（standalone），通过子进程运行
  - 动态端口分配、健康检查、优雅关闭与错误提示
- Next构建配置位于 next.config.ts，输出为standalone，禁用压缩以适配本地SSE流
- 构建脚本 scripts/build-electron.mjs 负责打包、下载并捆绑Node.js运行时、修复pnpm hoisting、剥离开发机路径、复制模板等
- 数据目录与资源路径在服务端路由中使用环境变量进行定位

```mermaid
graph TB
subgraph "Electron 主进程"
M["electron/main.ts<br/>应用生命周期/窗口/IPC"]
end
subgraph "Next.js 独立服务器"
S["standalone/server.js<br/>由主进程spawn启动"]
end
subgraph "构建产物"
N["node-runtime/<br/>平台化Node二进制"]
T[".next/standalone/<br/>模板与依赖"]
end
subgraph "Next 配置"
C["next.config.ts<br/>output: standalone, compress:false"]
end
subgraph "运行时环境"
ENV["环境变量<br/>PORT/HOSTNAME/NODE_ENV<br/>FORGE_*"]
end
M --> |spawn| S
M --> |读取| T
M --> |设置| ENV
C --> |生成| T
M --> |下载/放置| N
```

图表来源
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)
- [next.config.ts:3-12](file://next.config.ts#L3-L12)

章节来源
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [next.config.ts:3-12](file://next.config.ts#L3-L12)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)

## 核心组件
- Node二进制查找与运行时选择：根据是否打包决定使用内置node-runtime或系统node
- 端口分配：随机空闲端口，避免冲突
- 健康检查：轮询HEAD请求确认服务器就绪
- 进程管理：子进程stdout/stderr日志、退出事件、优雅关闭
- 环境变量与PATH扩展：注入PORT/HOSTNAME/NODE_ENV及FORGE_*，并扩展PATH以支持CLI工具
- 资源路径与模板：生产模式从resourcesPath读取standalone与templates

章节来源
- [electron/main.ts:18-30](file://electron/main.ts#L18-L30)
- [electron/main.ts:37-52](file://electron/main.ts#L37-L52)
- [electron/main.ts:54-71](file://electron/main.ts#L54-L71)
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)
- [electron/main.ts:105-118](file://electron/main.ts#L105-L118)
- [src/app/api/workspaces/[id]/init/route.ts:11-14](file://src/app/api/workspaces/[id]/init/route.ts#L11-L14)

## 架构总览
Electron主进程在应用准备后，按以下顺序执行：
- 开发模式：直接访问本地Next开发服务器
- 生产模式：动态分配端口、扩展PATH、设置环境变量、spawn独立服务器、等待健康检查、创建浏览器窗口并加载URL

```mermaid
sequenceDiagram
participant App as "Electron 应用"
participant Main as "electron/main.ts"
participant Builder as "scripts/build-electron.mjs"
participant Node as "Node.js 运行时"
participant Server as "Next 独立服务器"
App->>Main : app.whenReady()
alt 开发模式
Main->>Main : 设置 serverUrl = localhost : 3000
else 生产模式
Main->>Main : getFreePort()
Main->>Builder : 下载/放置 node-runtime
Main->>Node : spawn server.js (设置PORT/HOSTNAME/NODE_ENV/FORGE_ 及扩展PATH)
Node->>Server : 启动独立服务器
Main->>Main : waitForServer(HTTP HEAD)
end
Main->>Main : createWindow(serverUrl)
```

图表来源
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)

## 详细组件分析

### Node二进制查找与运行时策略
- 打包模式优先使用内置node-runtime（不同平台路径不同），若存在则使用；否则回退到系统node
- 开发模式直接使用系统node（需确保终端PATH可用）

```mermaid
flowchart TD
Start(["开始"]) --> CheckPackaged{"是否打包发布?"}
CheckPackaged --> |是| TryBundled["尝试内置node-runtime"]
TryBundled --> Found{"找到?"}
Found --> |是| UseBundled["使用内置node"]
Found --> |否| UseSystem["使用系统node"]
CheckPackaged --> |否| UseSystem
UseBundled --> End(["结束"])
UseSystem --> End
```

图表来源
- [electron/main.ts:18-30](file://electron/main.ts#L18-L30)

章节来源
- [electron/main.ts:18-30](file://electron/main.ts#L18-L30)

### 端口分配机制
- 使用临时TCP服务器监听端口0以获取随机空闲端口
- 关闭临时服务器后返回端口号，避免竞态

```mermaid
flowchart TD
A["调用 getFreePort()"] --> B["创建临时TCP服务器"]
B --> C["监听端口0"]
C --> D{"获取地址成功?"}
D --> |是| E["读取端口并关闭临时服务器"]
D --> |否| F["抛出错误"]
E --> G["返回端口"]
F --> H["reject"]
```

图表来源
- [electron/main.ts:37-52](file://electron/main.ts#L37-L52)

章节来源
- [electron/main.ts:37-52](file://electron/main.ts#L37-L52)

### 健康检查与超时处理
- 定期发送HEAD请求探测服务器状态
- 默认超时30秒，失败则重试，直至超时

```mermaid
flowchart TD
S["开始 waitForServer(url)"] --> T["记录起始时间"]
T --> Loop{"是否超过超时?"}
Loop --> |是| Timeout["reject 超时"]
Loop --> |否| Head["fetch(url, HEAD)"]
Head --> Ok{"响应ok?"}
Ok --> |是| Done["resolve 就绪"]
Ok --> |否| Retry["延时300ms重试"] --> Loop
```

图表来源
- [electron/main.ts:54-71](file://electron/main.ts#L54-L71)

章节来源
- [electron/main.ts:54-71](file://electron/main.ts#L54-L71)

### 子进程启动与环境变量配置
- spawn独立服务器，设置cwd为standalone目录
- 注入关键环境变量：PORT、HOSTNAME、NODE_ENV、FORGE_DATA_DIR、FORGE_RESOURCES_PATH、HOME
- 扩展PATH以包含常见CLI安装路径，便于SDK调用外部工具

```mermaid
sequenceDiagram
participant Main as "electron/main.ts"
participant Proc as "ChildProcess"
Main->>Proc : spawn(nodeBin, [serverScript], { env : {...}, cwd })
Proc-->>Main : stdout/stderr 日志
Proc-->>Main : exit(code)
Main->>Main : 记录退出码并清理引用
```

图表来源
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)

章节来源
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)

### 优雅关闭与进程生命周期
- before-quit事件中关闭文件监听器与服务器进程
- 窗口关闭时退出应用，确保资源释放

```mermaid
stateDiagram-v2
[*] --> Running
Running --> Quitting : before-quit
Quitting --> Stopped : kill serverProcess
Stopped --> [*]
```

图表来源
- [electron/main.ts:301-310](file://electron/main.ts#L301-L310)

章节来源
- [electron/main.ts:291-310](file://electron/main.ts#L291-L310)

### 开发模式 vs 生产模式差异
- 开发模式：直接加载本地localhost:3000，无需独立服务器
- 生产模式：构建standalone、下载node-runtime、spawn独立服务器、健康检查、创建窗口

章节来源
- [electron/main.ts:272-289](file://electron/main.ts#L272-L289)
- [next.config.ts:3-12](file://next.config.ts#L3-L12)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)

### 跨平台兼容性与PATH扩展
- 平台差异：Windows使用node.exe，Unix使用bin/node
- PATH扩展：在GUI环境下补充常见CLI安装路径，提升SDK可发现性

章节来源
- [electron/main.ts:18-30](file://electron/main.ts#L18-L30)
- [electron/main.ts:85-103](file://electron/main.ts#L85-L103)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)

### 资源路径处理与模板加载
- 生产模式下，初始化模板从resourcesPath/templates/init读取
- 开发模式下从项目根目录读取

章节来源
- [src/app/api/workspaces/[id]/init/route.ts:11-14](file://src/app/api/workspaces/[id]/init/route.ts#L11-L14)

### 错误处理与用户提示
- 启动失败弹窗提示，并引导安装Node.js
- 子进程stderr日志统一输出，便于诊断

章节来源
- [electron/main.ts:280-288](file://electron/main.ts#L280-L288)
- [electron/main.ts:124-126](file://electron/main.ts#L124-L126)

## 依赖关系分析
- electron/main.ts依赖：
  - Node标准库（net/fs/child_process/os/path）
  - Electron主进程API（app/BrowserWindow/ipcMain）
- 构建阶段依赖：
  - scripts/build-electron.mjs负责下载node-runtime、修复pnpm hoisting、剥离开发机路径、复制模板、清理隐私数据
- Next配置：
  - output: standalone，compress: false，serverExternalPackages排除原生模块

```mermaid
graph LR
Main["electron/main.ts"] --> Net["node:net"]
Main --> FS["node:fs"]
Main --> CP["node:child_process"]
Main --> OS["node:os"]
Main --> Path["node:path"]
Main --> Electron["electron APIs"]
Builder["scripts/build-electron.mjs"] --> NodeRuntime["node-runtime/"]
Builder --> Standalone[".next/standalone/"]
NextCfg["next.config.ts"] --> Standalone
```

图表来源
- [electron/main.ts:1-6](file://electron/main.ts#L1-L6)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [next.config.ts:3-12](file://next.config.ts#L3-L12)

章节来源
- [electron/main.ts:1-6](file://electron/main.ts#L1-L6)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [next.config.ts:3-12](file://next.config.ts#L3-L12)

## 性能考量
- 禁用压缩（compress:false）以避免SSE缓冲问题，适合本地桌面应用
- 使用standalone输出减少运行时依赖，提升启动稳定性
- 通过PATH扩展减少外部CLI查找失败导致的延迟
- 建议：
  - 在生产构建中保持standalone与node-runtime一致版本，避免ABI不匹配
  - 对于大体积模板，考虑按需加载或分层缓存
  - 监控子进程stderr日志，识别潜在阻塞点（如数据库锁、网络超时）

章节来源
- [next.config.ts:3-12](file://next.config.ts#L3-L12)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)

## 故障排查指南
- 无法启动服务器
  - 检查Node.js是否安装且可执行（开发模式）
  - 查看弹窗错误信息与控制台日志
  - 确认端口未被占用，或允许自动选择新端口
- 服务器启动但页面空白
  - 等待健康检查完成（默认30秒）
  - 检查PATH扩展是否包含所需CLI路径
- 资源路径异常
  - 确认生产模式下resourcesPath指向正确
  - 检查templates/init是否存在并可读
- 原生模块问题
  - 构建脚本会尝试重建better-sqlite3，若失败请检查构建环境与权限

章节来源
- [electron/main.ts:280-288](file://electron/main.ts#L280-L288)
- [electron/main.ts:54-71](file://electron/main.ts#L54-L71)
- [electron/main.ts:85-103](file://electron/main.ts#L85-L103)
- [src/app/api/workspaces/[id]/init/route.ts:11-14](file://src/app/api/workspaces/[id]/init/route.ts#L11-L14)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)

## 结论
该实现通过Electron主进程统一管理Next独立服务器的生命周期：在生产模式下采用standalone输出与内置Node运行时，结合动态端口分配、健康检查与优雅关闭，确保稳定可靠的本地桌面体验。开发模式与生产模式的差异化处理兼顾了开发效率与最终用户体验。建议持续关注原生模块兼容性、PATH扩展与SSE性能，以获得更佳的稳定性与性能表现。

## 附录
- 环境变量清单（主进程注入）
  - PORT：服务器端口
  - HOSTNAME：绑定地址
  - NODE_ENV：运行环境
  - FORGE_DATA_DIR：数据目录
  - FORGE_RESOURCES_PATH：资源路径
  - HOME：用户主目录
- 资源路径来源
  - 初始化模板：resourcesPath/templates/init（生产）或项目根目录（开发）
  - 数据目录：优先FORGE_DATA_DIR，否则~/.forge

章节来源
- [electron/main.ts:105-118](file://electron/main.ts#L105-L118)
- [src/app/api/workspaces/[id]/init/route.ts:11-14](file://src/app/api/workspaces/[id]/init/route.ts#L11-L14)
- [src/lib/forge-data.ts:20-26](file://src/lib/forge-data.ts#L20-L26)