一、阶段背景

在完成核心前端视图搭建和 Go Sidecar 的底层 Git 能力实现之后,IntelliGit 已经具备了一个功能完整的桌面 Git 客户端的基础形态。这一阶段的任务是让项目从"能用"迈向"智能"——把需求文档中定义的智能化特性从规划逐步落地。

按照任务规划,本阶段采用"双 P0 底座 + 三个 P1 工作流"的结构推进。Go Sidecar 方向的同学负责补充底层 Git 数据能力(AST 数据、冲突三方内容、Patch 操作等),Agent 方向则负责搭建 AI 工作流所需的全部基础设施。两个 P0 工作包并行推进,P1 工作流在此基础上展开。

本篇记录 Agent 框架的建设过程。

二、本阶段完成工作

  • src/renderer/src/agent/ 下建立完整 Agent 基础层,涵盖 LLM 客户端、工具注册、Prompt 模板、安全策略、输出解析、降级处理、运行时核心七个模块
  • 将 Agent 执行层从 Renderer 进程迁移至 Main 进程,引入 Vercel AI SDK 替换手写 fetch 客户端
  • 在 Main 进程新建 src/main/agent/ 目录,实现 agentRuntime.tsgitTools.ts 两个核心模块
  • 注册 agent:runTaskagent:pingLlm 两条 IPC 通道,并在 Preload 层完成安全桥接
  • 实现 LLM 配置层,包括 Zustand store、配置持久化 service、全局设置面板与状态栏 AI 指示灯
  • 排查并修复迁移过程中的两个问题:连接测试机制不合理、OpenAI 兼容接口始终返回 404

三、Agent 框架的设计思路

在动手实现之前,有一个问题需要先想清楚:AI 能力以什么形式接入现有代码?

最直接的做法是在各个需要 AI 的地方分别调用 LLM API。这样实现最快,但有几个明显的问题:三个 P1 工作流都需要调用 LLM,错误处理、降级逻辑、安全校验会在各处重复;LLM 的输出是非结构化文本,每个调用方都要各自处理解析和容错;切换 Provider 时需要改动多处代码。

因此决定先建立一个统一的 Agent 层,把 LLM 调用、工具注册、Prompt 管理、安全策略、输出解析、降级处理集中封装,P1 工作流只需要描述任务,不关心底层细节。agent/types.ts 定义了整个系统的数据契约——LlmConfigAgentTaskAgentResult<T>RiskLevel 等核心类型,其余模块围绕这套类型体系展开。

四、各模块实现

LLM 客户端(agent/llmClient.ts

第一版用纯 fetch 实现了 OpenAI 兼容接口和 Anthropic Claude 接口两套客户端,不依赖第三方 SDK。两套协议实现为独立的 Client 类,对外暴露统一接口,上层代码通过工厂函数创建,不感知 Provider 差异。baseUrl 字段的设计考虑了 OpenAI 兼容协议已成为国内大模型的事实标准——DeepSeek、通义千问等都支持,用户只需在设置界面填入对应的 API 地址即可切换,不需要改动代码。

工具注册(agent/toolRegistry.ts

实现了工具注册与调用机制,预声明了 13 个 Git 工具定义(getStatusgetDiffstageFilecreateCommit 等)。工具的实际执行逻辑由上层 P1 工作流在运行时注入,框架只负责路由与调用。这种"声明在 P0、实现在 P1"的分层设计,让 Agent 框架本身不依赖具体的 Git 操作实现,两部分可以独立维护。

Prompt 管理(agent/prompts/

实现了三套 Prompt 模板:commit.ts 基于暂存区 Diff 生成符合 Conventional Commits 规范的提交信息;nlAssistant.ts 负责自然语言意图解析,将用户输入转化为结构化 Git 操作计划,包含完整的风险分级说明;conflict.ts 负责冲突上下文分析与修复建议生成。

输出解析(agent/outputParser.ts

LLM 的输出并不总是规整的 JSON,即便 Prompt 里有明确要求,模型有时仍会在 JSON 前后附加说明文字,或者把内容包在 markdown 代码块里。outputParser.ts 实现了三层提取逻辑:优先从 markdown 代码块提取,其次匹配首个大括号对,最后尝试整体解析。在此之上预置了 COMMIT_MESSAGE_SCHEMANL_INTENT_SCHEMACONFLICT_RISK_SCHEMA 等常用 schema,P1 工作流直接使用 parseStructured<T> 即可完成输出的校验和反序列化。

安全策略(agent/safety.ts

基于正则规则识别高危和极高危 Git 操作,包括 --force--hardgit clean -f、向 main/master 强推等,匹配结果附带风险等级和阻止建议。

降级策略(agent/fallback.ts

taskType 分派降级结果:commit 任务返回基础模板提交信息,nl_assistant 任务返回提示用户配置 LLM 的文案,conflict 任务返回引导用户查看三方内容的操作说明。

五、框架迁移:从 Renderer 到 Main 进程

第一版框架运行在 Renderer 进程里,随着实现推进,这个位置的问题变得明显:Renderer 进程受 CSP 和 CORS 限制,向第三方 API 发起请求存在被拦截的风险;API Key 这类敏感凭据也不应出现在 Renderer 的运行时里。

迁移方向是把 Agent 执行层整体移入 Main 进程,Renderer 侧改写为 IPC 转发层,同时引入 Vercel AI SDK 替换手写的 fetch 客户端。

Main 进程侧新增的 agentRuntime.ts 是执行核心,负责根据 LlmConfig 构建模型实例,通过 generateText 驱动多轮 tool call,AbortController 控制 30 秒超时。gitTools.ts 定义了 18 个 Git 工具,按需加载,不同任务类型只暴露对应的工具子集。Renderer 侧的原有执行逻辑全部移除,llmClient.tstoolRegistry.tsgitTools.ts 一并删除,对应职责交给 Main 进程和 SDK 接管。

迁移过程中遇到了两个值得记录的问题。

第一个是连接测试机制。原来的 pingLlmConfiggenerateText 做连通性检测,每次实际上都在调用 LLM,速度慢且消耗 token。改为直接 fetch 各服务商的 GET /models 端点,只验证接口连通性和鉴权有效性。Anthropic 和 OpenAI 兼容接口鉴权方式不同,分别处理,错误信息返回前做脱敏处理。

第二个是 @ai-sdk/openai v3 的 Breaking Change。接入 DeepSeek、通义千问等 OpenAI 兼容接口时,AI 生成提交信息功能始终走降级路径,控制台里是 HTTP 404。排查后发现,v3 版本的 createOpenAI()(modelId) 默认创建 OpenAIResponsesLanguageModel,请求发往 /v1/responses,而大多数 OpenAI 兼容接口只实现了 /v1/chat/completions。改为 client.chat(modelId) 显式走 Chat Completions 路径,问题解决。这类 SDK 升级导致默认行为静默变更的问题,比直接报错更难排查,因为功能表面上看起来还在运行,只是静默地走了降级分支。

六、LLM 配置层与全局设置

Agent 框架的可用性依赖 LLM 配置的完整性。配置层包含三部分:llmConfigStore.ts 管理配置数据与连接状态(unconfigured / checking / ready / error 四态);llmConfigService.ts 负责配置的读取、写入与合并,写入时先读取全量配置再合并,避免覆盖仓库列表等其他字段;全局设置面板提供 Provider 选择、API Key 输入、Base URL、Model 名称、Temperature、Max Tokens 等配置项,以及连接测试按钮。状态栏的 AI 指示灯实时反映当前 LLM 配置和连通状态,四态动态显示,替换了此前的静态文本。

七、阶段小结

这一阶段建立了 IntelliGit 智能化特性的全部基础设施。框架完成后,P1 工作流的接入路径变得清晰:描述任务类型、传入上下文、调用 runAgentWithFallback,解析返回的结构化数据——底层的 LLM 调用、工具路由、安全拦截、降级处理都由框架统一承担。

从设计角度回顾,各层之间的分离——工具定义与执行实现分离、schema 定义与解析逻辑分离、任务类型与降级策略分离——在框架阶段看起来增加了一些前期工作量,但它们直接决定了后续 P1 工作流能否真正独立推进,而不是每个方向都在改同一层代码。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐