跳转到内容

选择语言

当前语言: 简体中文

Hagicode.Libs:统一集成多个 AI 编程助手 CLI 的工程实践

编辑此页
HagiCode for Windows Microsoft Store artwork
HagiCode for Windows 已上线 Microsoft Store
HagiCode for Windows 现已正式登陆 Microsoft Store,Windows 用户可以直接从商店完成安装并接收渠道更新。现在就打开商店页看看吧。
打开 Microsoft Store
Awesome Site banner: community-curated open-source collections
Awesome Site:社区精选开源合集
在开源社区精心整理的合集中,找到下一个工具、想法或灵感。从感兴趣的主题出发,用熟悉的语言阅读,再回到原始来源深入探索。
探索精选合集
Awesome Design banner: a gallery of DESIGN.md design systems
Awesome Design:DESIGN.md 设计系统画廊
通过实时预览与 README 参考浏览精选设计系统,再把 DESIGN.md 复制进你的项目,让 AI 代理按它构建风格一致的页面。
浏览设计画廊
OpenSpec banner: agree on the spec, then build with AI
OpenSpec:先对齐规范,再让 AI 写代码
OpenSpec 是面向 AI 编程的轻量规范层:先描述一项变更,由 AI 起草提案、规范、设计与任务,你审阅确认后再动手实现,完成后归档为持续更新的规范。没有僵化的阶段门槛,适用于已有代码库,并能搭配你正在使用的各类 AI 助手。
了解 OpenSpec
OmniRoute Docs banner: one endpoint for many AI providers
OmniRoute 文档:一个端点连接众多 AI 服务商
了解 OmniRoute 如何通过同一个端点路由众多 AI 服务商与模型,并支持免费额度与自动回退,让你的编码工具持续可用。
查看 OmniRoute 文档

Hagicode.Libs:统一集成多个 AI 编程助手 CLI 的工程实践

在开发 HagiCode 项目的过程中,我们需要同时集成 Claude Code、Codex、CodeBuddy 等多个 AI 编程助手 CLI。每个 CLI 的接口、参数、输出格式都不一样,重复的集成代码让项目越来越难以维护。本文分享我们如何通过 HagiCode.Libs 库构建统一抽象层,解决这个工程痛点——也算是我们踩过的坑,积累下来的一点经验罢了。

背景

现在的 AI 编程助手市场挺热闹的,除了 Claude Code,还有 OpenAI 的 Codex、智谱的 CodeBuddy 等等。作为一个 AI 代码助手项目,HagiCode 需要在多个子项目(桌面端、后端、Web 等)中集成这些不同的 CLI 工具。

一开始问题还不大,集成一个 CLI 也就是几百行代码的事儿。只是随着要支持的 CLI 越来越多,事情就开始变得麻烦了——

每个 CLI 有不同的命令行参数格式,环境变量的要求也不一样,输出格式更是五花八门——有的输出 JSON,有的流式 JSON,有的就是纯文本。再加上跨平台兼容性问题,Windows 和 Unix 系统的可执行文件发现和进程管理机制完全不同,代码重复度越来越高。其实这也无非就是 Ctrl+C、Ctrl+V 多了一点,但维护起来可就头疼了。

最头疼的是,每次要新增一个 CLI 功能支持,就得在好几个项目里改同样的代码。这种方式显然不是长久之计——代码也是有脾气的,重复太多它也会闹别扭。

关于 HagiCode

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个开源的 AI 代码助手项目,需要同时维护前端 VSCode 扩展、后端 AI 服务、跨平台桌面客户端等多个子项目。怎么说呢,正是这种多语言、多平台的复杂场景,促成了 HagiCode.Libs 的诞生——算是被逼出来的,也罢。

分析:寻找共同点

虽然这些 AI 编程助手 CLI 各有特点,但从技术层面来看,它们存在明显的共同特征:

相似的交互模式:都是启动 CLI 进程,发送提示词,接收流式响应,解析消息,最后会话结束或继续——这一套流程,说到底都是一个模子刻出来的。

相似的配置需求:都需要 API 密钥认证、工作目录设置、模型选择、工具权限控制、会话管理。毕竟大家都是吃 API 这碗饭的,差别无非是口味不同。

跨平台挑战一致:都需要解决可执行文件路径解析(claude vs claude.exe vs /usr/local/bin/claude)、进程启动和环境变量处理、Shell 命令转义和参数构建等问题。这跨平台的事儿,说多了都是泪——Windows 和 Unix 的差异,只有踩过坑的人才知道。

基于这些分析,我们需要一个统一的抽象层来提供一致的接口,封装跨平台的 CLI 发现逻辑,处理流式输出的解析,同时支持依赖注入和非 DI 场景使用。这事儿想想就头大,但还是要面对——毕竟是自己的项目,哭着也要做完。

解决方案:HagiCode.Libs

我们创建了 HagiCode.Libs —— 一个轻量级的 .NET 10 库工作空间,采用 MIT 开源协议,现已发布在 GitHub。虽然不是什么惊天地泣鬼神的大作,但解决实际问题,还是挺香的。

项目结构

HagiCode.Libs/
├── src/
│ ├── HagiCode.Libs.Core/ # 核心功能
│ │ ├── Discovery/ # CLI 可执行文件发现
│ │ ├── Process/ # 跨平台进程管理
│ │ ├── Transport/ # 流式消息传输
│ │ └── Environment/ # 运行时环境解析
│ ├── HagiCode.Libs.Providers/ # 提供者实现
│ │ ├── ClaudeCode/ # Claude Code 提供者
│ │ ├── Codex/ # Codex 提供者
│ │ └── Codebuddy/ # CodeBuddy 提供者
│ ├── HagiCode.Libs.ConsoleTesting/ # 测试框架
│ ├── HagiCode.Libs.ClaudeCode.Console/
│ ├── HagiCode.Libs.Codex.Console/
│ └── HagiCode.Libs.Codebuddy.Console/
└── tests/ # xUnit 测试

设计目标

在设计 HagiCode.Libs 时,我们遵循了几个原则——毕竟也都是踩过的坑,总结出来的经验:

零重型框架依赖:不依赖 ABP 或其他大型框架,保持轻量级。这年头,依赖越少,麻烦越少——谁还没被依赖地狱毒打过呢。

跨平台支持:Windows、macOS、Linux 原生支持,不需要针对不同平台写不同的代码。一套代码走天下,也挺好的。

流式处理:使用异步流处理 CLI 输出,更符合现代 .NET 的编程模式。毕竟时代在变,异步才是王道。

灵活集成:既支持依赖注入场景,也允许直接实例化使用。萝卜青菜,各有所爱,怎么方便怎么来。

使用方式

通过依赖注入

如果你的项目已经在使用依赖注入(比如 ASP.NET Core 或通用主机),可以直接集成——这也算是个孩子,虽然不大,但挺乖的:

using HagiCode.Libs.Providers;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddHagiCodeLibs();
await using var provider = services.BuildServiceProvider();
var claude = provider.GetRequiredService<ICliProvider<ClaudeCodeOptions>>();
var options = new ClaudeCodeOptions
{
ApiKey = "your-api-key",
Model = "claude-sonnet-4-20250514"
};
await foreach (var message in claude.ExecuteAsync(options, "Hello, Claude!"))
{
Console.WriteLine($"{message.Type}: {message.Content}");
}

直接实例化

如果是简单的脚本或者不使用 DI 的场景,直接创建实例也行——说白了就是看个人喜好:

var claude = new ClaudeCodeProvider();
var options = new ClaudeCodeOptions
{
ApiKey = "sk-ant-xxx",
Model = "claude-sonnet-4-20250514"
};
await foreach (var message in claude.ExecuteAsync(options, "帮我写一个快速排序"))
{
// 处理消息
}

两种方式使用的是同一套底层实现,你可以根据项目实际情况选择合适的集成方式。这世界本就没有标准答案,适合自己的才是最好的——虽然这话有点老套,但确实是这么个理儿。

实践经验分享

1. 专用测试控制台

每个提供者都有专用的测试控制台项目,方便独立验证集成效果——怎么说呢,测试这件事,要么不做,要做就做到位:

终端窗口
# Claude Code 测试
dotnet run --project src/HagiCode.Libs.ClaudeCode.Console -- --test-provider
dotnet run --project src/HagiCode.Libs.ClaudeCode.Console -- --test-all claude
# CodeBuddy 测试
dotnet run --project src/HagiCode.Libs.Codebuddy.Console -- --test-provider codebuddy-cli
# Codex 测试
dotnet run --project src/HagiCode.Libs.Codex.Console -- --test-provider codex-cli

测试场景覆盖了几个关键场景:

  • Ping:健康检查,确认 CLI 可用
  • Simple Prompt:基本提示测试
  • Complex Prompt:多轮对话测试
  • Session Restore/Resume:会话恢复测试
  • Repository Analysis:代码库分析测试

这种独立的测试控制台设计在调试时特别有用,可以快速定位问题是在 HagiCode.Libs 层还是 CLI 本身。这调试嘛,说白了就是看问题出在哪儿——方向对了,就成功了一半。

2. 跨平台 CI/CD 验证

跨平台兼容性是 HagiCode.Libs 的核心目标之一。我们配置了 GitHub Actions 工作流 .github/workflows/cli-discovery-cross-platform.yml,在 ubuntu-latest、macos-latest、windows-latest 三个平台上运行真实的 CLI 发现验证。

这确保了每次代码变更都不会破坏跨平台兼容性。本地开发时也可以通过以下命令复现——总不能让 CI 帮你背所有锅,自己本地也要能跑起来:

终端窗口
npm install --global @anthropic-ai/claude-code@2.1.79
HAGICODE_REAL_CLI_TESTS=1 dotnet test --filter "Category=RealCli"

3. 消息流处理

HagiCode.Libs 使用异步流处理 CLI 输出,这种方式比传统的回调或事件模式更符合现代 .NET 的异步编程风格——说到底,这就是技术的进步,谁也挡不住:

public async IAsyncEnumerable<CliMessage> ExecuteAsync(
TOptions options,
string prompt,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
// 启动 CLI 进程
// 解析流式 JSON 输出
// 生成 CliMessage 序列
}

消息类型包括:

  • user:用户消息
  • assistant:助手响应
  • tool_use:工具调用
  • result:会话结束

这种设计让调用方可以灵活地处理流式输出,比如实时显示、缓冲后处理、或者转发到其他服务。美又何必在乎天晴阴呢?重要的是思路打开了,怎么用都成。

4. Git 仓库探索

HagiCode.Libs.Exploration 模块提供了 Git 仓库发现和状态检查功能,这在分析代码库场景特别有用——这也是被逼出来的功能,谁让 HagiCode 需要分析代码库呢:

// 发现 Git 仓库
var repositories = await GitRepositoryDiscovery.DiscoverAsync("/path/to/search");
// 获取仓库信息
var info = await GitRepository.GetInfoAsync(repoPath);
Console.WriteLine($"Branch: {info.Branch}, Remote: {info.RemoteUrl}");
Console.WriteLine($"Has uncommitted changes: {info.HasUncommittedChanges}");

HagiCode 的代码分析功能就用到了这个模块来识别项目结构和 Git 状态。算是物尽其用,也算是个孩子,没白养。

注意事项

基于我们在 HagiCode 项目中的实践,有几个地方需要特别注意——都是事儿,事儿,事儿:

API 密钥安全:不要将 API 密钥硬编码到代码中,使用环境变量或配置管理。HagiCode.Libs 支持通过 Options 对象传递配置,方便集成各种配置源。毕竟安全这件事,怎么小心都不为过。

CLI 版本锁定:CI/CD 中我们锁定了特定版本(如 @anthropic-ai/claude-code@2.1.79)以减少版本漂移带来的不确定性。本地开发时建议也使用固定版本。这版本的事儿,说多了都是泪——不固定版本,分分钟教你做人。

测试分类:默认测试使用假提供者保持确定性和速度,真实 CLI 测试需要显式启用。这样既保证了 CI 的快速反馈,又能在需要时进行真实环境验证。这平衡木走起来,也不容易——快和稳,总是需要取舍。

会话管理:不同 CLI 的会话恢复机制不同,Claude Code 使用 .claude/ 目录存储会话,Codex 和 CodeBuddy 各有自己的方式。使用时要注意查看各自文档,了解会话持久化的具体机制。这也罢了,了解清楚总没坏处。

总结

HagiCode.Libs 是我们在开发 HagiCode 过程中,为了解决多 CLI 集成的重复工程问题而构建的统一抽象层。它通过提供一致的接口、封装跨平台细节、支持灵活的集成方式,大大降低了集成多个 AI 编程助手的工程复杂度。一切都淡了——但经验留下了。

如果你也在项目中需要集成多个 AI CLI 工具,或者对跨平台进程管理、流式消息处理感兴趣,欢迎来 GitHub 看看。项目采用 MIT 开源协议,欢迎贡献和反馈。终究是缘分一场,来都来了,不妨交个朋友。

本文分享的方案是 HagiCode 实际踩坑、实际优化出来的。这又有什么办法呢?踩坑嘛,正常——如果你觉得这套方案有价值,说明我们的工程实力也还算过得去。那么 HagiCode 本身,也值得关注一下,说不定有惊喜呢。

参考资料


如果本文对你有帮助:

版权说明

感谢您的阅读,如果您觉得本文有用,欢迎点赞、收藏和分享支持。 本内容采用人工智能辅助协作,最终内容由作者审核并确认。

开始使用 HagiCode

一次安装,几分钟上手

HagiCode for Windows 在 Microsoft Store 免费提供。打开商店即可安装并保持更新;也可以先对比各版本与定价,再决定从哪个渠道开始。

让想法变成真正交付的软件。

HagiCode 是面向项目开发的 AI 编码工作台:用 OpenSpec 工作流规划变更,多 Agent 并行执行,再由 Hero Dungeon 让进度一目了然,把想法变成真正交付的软件。

智能
OpenSpec 工作流把意图变成从提案到交付的可执行路径。
高效
多 Agent 并行推进调研、实现与审阅。
有趣
Hero Dungeon 让长时间编码看得见:英雄、进度与成就。