Skip to content

refactor(ipc): IPC 分层重构——controller + service 分层,契约独立成 @meebox/ipc 包#76

Merged
huhamhire merged 9 commits into
devfrom
refactor/ipc-service-layer
Jun 18, 2026
Merged

refactor(ipc): IPC 分层重构——controller + service 分层,契约独立成 @meebox/ipc 包#76
huhamhire merged 9 commits into
devfrom
refactor/ipc-service-layer

Conversation

@huhamhire

Copy link
Copy Markdown
Owner

背景

apps/desktop/src/main/ipc.ts 此前膨胀到约 2450 行:单个 registerIpcHandlers 闭包里混杂 IPC handler 注册、pr-agent run 队列、Agent 编排、AutoPilot 调度与大量内联工具/提示词。本 PR 将其按职责分层重构,纯结构性、不改运行行为

改动概览(按 commit)

  1. Service 层 + 契约独立成包 — IPC 契约从 @meebox/shared 拆出为新内部包 @meebox/ipc(按域分文件 app/pr/config/agent/events/common);main 抽出 services/ 业务层。
  2. controller 层 + PrService — IPC handler 抽到 controllers/(app/pr/config/agent),PR 领域操作(定位/adapter/镜像/diff base/评论缓存)类化为 PrService
  3. 服务类化RunQueueService / AgentOrchestratorService 由工厂闭包改为 class,封装各自可变实例状态。
  4. 原生 handler + 单例上下文 — controller 回归原生 ipcMain.handle 监听器 (event, req),去掉自定义包装层;运行时上下文 ServiceContextgetContext() 进程级单例提供(IpcContext 更名 ServiceContext,命名不再误导成属于契约包)。
  5. pragent 归 Agent 域pragent:*(run 执行层)从 PR 域整体移到 Agent 域(契约/controller/注册三层一致)。
  6. 提示词抽取 — pr-agent 的 EXTRA_INSTRUCTIONS / anchor / 排版 / 语言指示等内联提示词从 run 队列抽到 services/pragent-prompts.ts 整体维护。

最终结构

packages/ipc/                     # IPC 契约(按域)
apps/desktop/src/main/
├── ipc.ts                        # 薄入口:建上下文/服务 → 注册 → 返回控制句柄
├── controllers/                  # app/pr/config/agent + types.ts(IpcController)
└── services/
    ├── context.ts (ServiceContext + 单例)
    ├── pr-service.ts (class PrService)
    ├── run-queue.ts (class RunQueueService)
    ├── agent-orchestrator.ts (class AgentOrchestratorService)
    ├── pragent-prompts.ts (提示词)
    ├── app.ts / comments.ts / broadcast.ts / usage.ts (领域/跨域工具)

验证

npm run lint / typecheck / build 全绿(CI 同款)。IPC 通道请求/响应语义、renderer 业务均未改动(仅 import 路径切换)。

🤖 Generated with Claude Code

huhamhire and others added 6 commits June 18, 2026 11:02
ipc.ts 从 2449 行收薄至约 50 行,仅做上下文装配与各域 handler 注册;
业务实现下沉到 apps/desktop/src/main/services/:

- common/ 公共工具:broadcast / pr-lookup(收口 adapter 查找)/ mirror /
  comments-cache / usage;context.ts 聚合依赖与公共工具
- 跨域 service:run-queue(pr-agent run 队列)、agent-orchestrator(编排 + AutoPilot)
- 四域 handler:app / pr / config / agent,各自维护领域私有工具

IPC 契约从 packages/shared/src/ipc.ts 拆分迁入新内部包 @meebox/ipc,按业务领域
分文件(app/pr/config/agent/events/common);renderer/preload/main 三侧改从
@meebox/ipc 导入。SyncProgressEvent 因被 repo-mirror 消费,归位到 @meebox/shared。

纯结构性重构,不改运行行为;lint/typecheck/test/build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
承接上一轮 service 层抽取,进一步按 request-controller 模式整理 main 侧 IPC:

- handler 与 ipcMain.handle 解耦:每个 handler 是具名 controller(统一签名
  (ctx, req, evt) => …),通道字符串只在 ipc.ts 集中 handle() 一次绑定,带每通道行内注释
- controller 从 service 层剥离到 apps/desktop/src/main/controllers/(app/pr/config/agent),
  register.ts 提供 IpcController 类型 + handle() 薄类型包装
- 解散 services/common/:broadcast / usage 上提为独立纯函数模块;pr-lookup / mirror /
  comments-cache 合并为 PrService 类(强 PR 领域,依赖构造注入),controller 经 ctx.pr.* 调用
- run-queue / agent-orchestrator 保持工厂函数(内聚单域,不强行类化)
- 主进程运行时上下文 IpcContext 改名 ServiceContext(不再误导成属于 @meebox/ipc 契约包)

纯结构性重构,不改运行行为;lint / typecheck / build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
把两个持有可变实例状态的服务从工厂闭包改为 class,使 service 层封装一致
(PrService / RunQueueService / AgentOrchestratorService 均为 class,纯工具仍是函数模块):

- run-queue.ts → class RunQueueService:waiting / active / maxConcurrency /
  embeddedSecretsEnsured 为私有字段,executeRun / pump / ensureEmbeddedSecrets 为私有方法;
  纯语言助手(languageDirectiveFor / askLanguageSuffixFor / stripAskQuestionEcho)保留为模块函数
- agent-orchestrator.ts → class AgentOrchestratorService:agentControllers / runningAgentPrs /
  autopilotBusy 私有字段,编排各步骤为私有方法
- runAutopilotIfDue 消除冗余的 void (async () => {})() 闭包:异步 pass 体抽成具名私有方法
  runAutopilotPass,busy 锁置位 / 复位在其内成对管理
- ipc.ts 改用 new RunQueueService / new AgentOrchestratorService 装配

纯结构性重构,不改运行行为;lint / typecheck / build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
handler 回归标准 ipcMain.handle 形态,去掉自定义 handle 包装层:

- controller 改为原生监听器签名 (event, req) => response(IpcController 类型仍绑通道契约
  做 body 类型校验);不带 ctx 参数,依赖经 getContext() 进程级单例取用
- ServiceContext 装配后经 setControllerContext 安装为单例;controllers/register.ts 去掉 handle
  包装函数,更名 controllers/types.ts 只留 IpcController 类型
- ipc.ts 直接 ipcMain.handle('channel', controller) 注册,每通道一行 + 行内场景注释
- diff:listComments 的 in-flight 去重改为「显式构造 Promise(内部 async IIFE 顺序 await)+ 同步
  set 进 map」,并补注释说明为何不能整体写成顶层 async(首个 await 挂起前需先注册 Promise)
- controller 文档注释统一 3 行 /** */,领域分节统一块注释;IpcController 注释 JSDoc 化

纯结构性重构,不改运行行为;lint / typecheck / build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pragent:*(pr-agent run 执行层:触发 / 取消 / 队列 / 历史)本是「在 PR 上跑 AI 评审工具」,
与 agent 编排同源(agent:run / AutoPilot 也经同一 run 队列派发),而非通用 PR CRUD。
故从 PR 域整体移到 Agent 域,三层一致:

- 契约 @meebox/ipc:pragent:run/listRuns/getRun/clearRuns/cancel/queue 从 PrChannels 移到
  AgentChannels(ReviewRun/PragentRunInfo import 随迁);IpcChannels 为交集,renderer 零改动
- controller:runPragent/cancelPragent/getQueue/listRuns/getRun/clearRuns 从 pr.ts 移到 agent.ts,
  run 相关 poller import 随迁
- 注册 ipc.ts:6 个 ipcMain.handle('pragent:…') 从「PR 操作」组移到「Agent 交互」组

纯结构性重构,不改运行行为;lint / typecheck / build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
run 队列执行逻辑里夹杂大段内嵌提示词(anchor marker / 排版 / 语言指示 / ask 语言后缀 /
回显去重)不合理;统一抽到 services/pragent-prompts.ts 整体维护,纯字符串构造、无 I/O:

- buildExtraInstructions:收口 EXTRA_INSTRUCTIONS 的按序拼接(语言 / anchor / 排版 / PR 上下文 / 规则)
- extraInstructionsEnvKey:EXTRA_INSTRUCTIONS 的 env key 映射
- askLanguageSuffixFor / stripAskQuestionEcho:/ask 语言后缀与输出回显去重
- languageDirectiveFor / anchorMarkerDirective / reviewLayoutDirective 为模块私有,长文本集中此处

run-queue.ts 的 executeRun 只保留「收集 prContext + 命中规则」的 I/O,再调上述函数装配 env,
瘦身约 130 行。纯结构性重构,不改运行行为;lint / typecheck / build 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@huhamhire huhamhire added the refactor 代码重构(不改运行行为) label Jun 18, 2026
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

合入 dev 前端 features 域重组(ChatPane/组件按 features 拆分、SettingsModal/App 组合根、
样式分区等)。冲突收口:renderer 侧统一从迁出后的 @meebox/ipc 导入 IPC 契约类型
(IpcChannels / ConnectionSummary / DiffChangedFile / PragentRunInfo),新结构文件
(features/chat、layout/StatusBar 等)按域采纳 dev 版本后改正契约 import 来源。
lint / typecheck / test / build 四步全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@huhamhire huhamhire added this to the 代码质量重构 milestone Jun 18, 2026
huhamhire and others added 2 commits June 18, 2026 20:05
承接 #78:本机 CLI 模式下 codex 编排通道改用 model_reasoning_effort=low。
重构后该 env 注释位于 services/agent-orchestrator.ts(dev 侧对应改动在 ipc.ts),
此处同步表述,避免合并 dev 后注释口径不一致。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ayer

# Conflicts:
#	apps/desktop/src/main/ipc.ts
@huhamhire huhamhire merged commit 3408233 into dev Jun 18, 2026
1 check passed
@huhamhire huhamhire deleted the refactor/ipc-service-layer branch June 18, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor 代码重构(不改运行行为)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant