当前位置: 首页 > news >正文

从零开始:如何将 Reasonix CLI 集成到 HagiCode 系统中

从零开始:如何将 Reasonix CLI 集成到 HagiCode 系统中

本文分享了将 Reasonix CLI 作为一等 Agent Provider 集成到 HagiCode 系统的完整技术实践,涵盖三层架构设计、关键技术决策和前后端实现细节。

背景

Reasonix CLI,说起来也是个挺有意思的东西。它是一个基于 ACP(Agent Communication Protocol)的 AI 代码助手工具,提供了强大的流式传输和会话管理能力。其实在 HagiCode.Libs 层,我们已经把它的底层实现都搞定了,只是这些组件还处在孤立的状态,就像一个个漂亮的珍珠,还没串成项链。用户无法通过 Hero 职业选择、会话执行链路或监控面板来使用它,这多少有点可惜。

我们面临的问题是:如何将 Reasonix 提升为与 Codex、Hermes 等同等级的一等 Agent Provider,实现完整的后端路由和前端展示?这可不是简单地注册一个枚举值就能了事的,而是需要构建从底层抽象到用户界面的完整链路。就像盖房子,不能只打个地基就完事了,总得把墙砌起来,屋顶盖上去。

这个集成的挑战在于,Reasonix 作为一个本地 CLI 工具,有自己的性格和脾气。比如它不需要连接字符串,所有参数都是用户运行时配置;它可能根本没有安装,需要优雅降级处理;它兼容 anthropic 系列模型,但又有自己的 effort、budget 等 ACP 特有参数。这就像一个人,有自己独特的处事方式,不能硬来。

经过仔细的架构设计和多轮讨论,我们最终采用了一套清晰的三层架构方案,将 Reasonix 成功集成到系统中。这套方案不仅解决了眼前的问题,也为后续类似 CLI Provider 的集成提供了可复用的模式。其实很多事情就是这样,一旦找到了正确的方法,后面的路就好走多了。

关于 HagiCode

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个开源的 AI 代码助手项目,致力于为开发者提供强大的代码生成、重构和优化能力。在开发过程中,我们遇到了各种各样的技术挑战,将 Reasonix 集成为一等 Agent Provider 就是其中之一。如果你觉得本文分享的方案有价值,说明我们的工程实践还不错,那么 HagiCode 本身也值得关注一下。

核心内容

技术架构设计

系统采用了清晰的三层架构来分离关注点,每层都有明确的职责边界:

HagiCode.Libs 层:这一层已经完成,提供了 CLI provider 的抽象和具体实现。它定义了ICliProvider<ReasonixOptions>接口,实现了ReasonixProvider来处理 ACP 流式传输和会话管理,同时支持 effort、budget、yolo、transcript 等参数。这一层的职责是提供稳定、可复用的底层能力,不涉及任何业务逻辑。就像房子的地基,虽然看不见,但很重要。

hagicode-core 层:这是我们本次集成的重点。它负责将底层抽象桥接到系统的统一接口上。具体工作包括注册AIProviderType.ReasonixCli = 12枚举值,创建ReasonixCliProvider作为 thin adapter 桥接 Libs 层,实现ReasonixGrain处理会话状态和执行流,以及集成 Hero 系统进行参数映射和配置管理。这一层的核心是协调各组件,构建完整的业务链路。就像房子的承重墙,把各个部分连接起来。

web 层:负责向用户展示和收集配置。我们需要重新生成 OpenAPI 类型以支持新枚举值,实现视觉类型映射让 Reasonix 有自己的图标和显示名称,创建 CLI 参数配置表单让用户可以配置各个参数,以及添加多语言支持。这一层的重点是用户体验和交互设计。就像房子的装修,做得好不好直接影响住得舒不舒服。

这样的分层设计让每一层都专注于自己的职责,降低了系统的复杂度,也便于后续维护和扩展。其实很多时候,把事情分清楚,反而会更简单。

关键技术决策

在实现过程中,我们做了几个关键的技术决策,这些决策对最终的架构和用户体验都有重要影响。

决策一:使用专用 Grain

我们创建了独立的ReasonixGrain : IReasonixGrain, IExecutorStreamGrain,而不是尝试复用某个共享的 Grain。这个决策遵循了系统现有的 11 个 provider 的既定模式。虽然看起来可能会有些代码重复,但专用 Grain 让我们可以针对 Reasonix 的特性做精细化的控制,比如它特有的会话绑定机制和 ACP 消息映射。我们还定义了一个空的响应 DTOReasonixResponse作为类型区分符,虽然它不包含实际数据,但在类型系统中起到了重要的作用。就像每个人都有自己的房间,哪怕空着,也是自己的空间。

决策二:不创建专用 Settings 类

与某些需要连接字符串的 Provider 不同,Reasonix 的所有配置都是用户运行时设置的,不需要启动时验证。因此我们没有创建专用的 Settings 类,而是将所有配置存储在AIProviderOptions.Providers[ReasonixCli].Settings字典中。这种模式与 Qoder、Kiro、Kimi 等其他本地 CLI Provider 保持一致,简化了代码结构,也避免了不必要的抽象层。支持的设置键包括:effortbudgetUsdtranscriptPathenableYoloargumentsstartupTimeoutMsreasoning。有时候简单点,反而更好。

决策三:Provider 策略健康监控

Reasonix 是用户本地安装的 CLI,可能根本没有安装,或者不在系统 PATH 中。这种情况下,我们不应该直接报错,而是应该优雅地降级处理。我们使用了Provider策略,通过CommandUtil.TryResolveExecutablePath来检查 CLI 是否可用。如果检查失败,UI 会显示为"不可用",但不会影响系统的其他部分。这种设计让系统更加健壮,也给用户清晰的反馈。毕竟谁也不会希望因为一个小问题,整个系统都挂了。

决策四:经济系统分类

在 HagiCode 系统中,不同的 Provider 有不同的经济系统分类。我们决定让 Reasonix 默认使用'claude'经济系统分类,因为 Reasonix 本身兼容 anthropic 系列模型。目前只有 Codex 和 Copilot 有专用的经济系统分类,其他 Provider 都是复用现有的分类。这样既保持了系统的简洁性,又能正确处理计费和成本统计。复用也是个智慧,不需要什么都从头来。

决策五:模型兼容性

Reasonix 通过--model标志支持多种模型,特别是 anthropic 系列。我们在secondary-professions.index.json中添加了兼容性映射,让用户可以在 Reasonix 中选择这些模型。这种设计既尊重了 Reasonix 的能力,又保持了系统的一致性,用户无需理解底层的区别,就能顺畅地使用各种模型。用户也不容易,还是让他们简单点好。

后端实现细节

后端实现分为几个关键部分,每部分都有其独特的技术要点。

枚举和类型注册

首先,我们需要在系统中注册新的 Provider 类型:

// AIProviderType.cspublicenumAIProviderType{// ... 其他 providerReasonixCli=12,}// AIProviderTypeExtensions.csprivatestaticreadonlyDictionary<string,AIProviderType>_typeMap=new(){// ... 其他映射["Reasonix"]=AIProviderType.ReasonixCli,["reasonix"]=AIProviderType.ReasonixCli,["reasonix-cli"]=AIProviderType.ReasonixCli,["ReasonixCli"]=AIProviderType.ReasonixCli,};

这个枚举值需要与其他并发变更协调,避免冲突。我们选择了 12 这个值,因为它是下一个可用的编号。就像排队一样,总得有个先后顺序。

Thin Adapter 实现

ReasonixCliProvider是连接 Libs 层和系统统一接口的关键组件:

publicsealedclassReasonixCliProvider:IAIProvider,IVersionedAIProvider,IAsyncDisposable{privatestaticreadonlyIReadOnlyList<string>SupportedSettingKeys=["effort","budgetUsd","transcriptPath","enableYolo","arguments","startupTimeoutMs","reasoning"];privatereadonlyICliProvider<ReasonixOptions>_provider;privatereadonlyConcurrentDictionary<string,string>_sessionBindings=new(StringComparer.Ordinal);publicasyncIAsyncEnumerable<AIStreamingChunk>StreamCoreAsync(AIRequestrequest,string?sessionId=null,[EnumeratorCancellation]CancellationTokencancellationToken=default){varoptions=BuildOptions(request,sessionId);awaitforeach(varmessagein_provider.StreamAsync(options,cancellationToken)){yieldreturnMapToStreamingChunk(message);}}privateReasonixOptionsBuildOptions(AIRequestrequest,string?sessionId){returnnewReasonixOptions{ExecutablePath=GetExecutablePath(),WorkingDirectory=GetWorkingDirectory(),Model=_config.Model,Effort=_config.Settings.GetValueOrDefault("effort","medium"),Budget=_config.Settings.GetValueOrDefault("budgetUsd",10.0),Yolo=_config.Settings.GetValueOrDefault("enableYolo",false),TranscriptPath=_config.Settings.GetValueOrDefault("transcriptPath"),Arguments=_config.Settings.GetValueOrDefault("arguments",""),StartupTimeout=GetStartupTimeout(),EnvironmentVariables=_environmentVariables,CessionId=sessionId??GetCessionId()};}}

这个 adapter 的关键职责是:

  1. 验证配置参数,拒绝不支持的设置键
  2. 维护会话绑定关系,支持会话恢复
  3. 将 ACP 消息映射到系统的统一格式
  4. 使用ProviderErrorAutoRetryCoordinator实现自动重试

就像一个翻译官,把一种语言翻译成另一种语言,还得保证意思准确无误。

Orleans Grain 实现

ReasonixGrain负责处理会话状态和执行流:

publicclassReasonixGrain:Grain,IReasonixGrain,IExecutorStreamGrain{privatereadonlyDictionary<string,ExecutorToolLifecycleStatus>_toolLifecycleState=new(StringComparer.Ordinal);publicIAsyncEnumerable<ReasonixResponse>ExecuteCommandStreamAsync(stringcommand,string?heroId=null,CancellationTokentoken=default,string?executionMessageId=null,string?systemMessage=null,Dictionary<string,string>?requestSettings=null){varrequest=BuildRequest(command,isEdit:false,heroId,executionMessageId,systemMessage,requestSettings);returnSendAsync(request,heroId,token);}privateasyncIAsyncEnumerable<ReasonixResponse>SendAsync(AIRequestrequest,string?heroId,[EnumeratorCancellation]CancellationTokentoken){_cancellationTokenSource=newCancellationTokenSource();varlinkedToken=CancellationTokenSource.CreateLinkedTokenSource(token,_cancellationTokenSource.Token);varprovider=awaitResolveReasonixProviderAsync(heroId);awaitforeach(varchunkinprovider.StreamAsync(request,linkedToken.Token)){varresponse=BuildChunkResponse(chunk);yieldreturnresponse;}}privateasyncTask<IAIProvider>ResolveReasonixProviderAsync(string?heroId){// Hero 感知的配置回退逻辑varconfig=awaitHeroProviderResolver.ResolveAsync(AIProviderType.ReasonixCli,heroId);return_aiProviderFactory.CreateProvider(AIProviderType.ReasonixCli,config);}}

Grain 的核心功能包括:

  1. 使用[PersistentState("reasonix-interop")]维护会话状态
  2. 实现 Hero 感知的配置回退逻辑
  3. 追踪工具生命周期状态
  4. 支持取消令牌链,确保执行可以及时中断

这就像一个管家,把事情安排得井井有条。

Hero 系统集成

Hero 系统是 HagiCode 的职业配置系统,我们需要将 Reasonix 集成到这个体系中:

// HeroAppService.cs// Family 推断AIProviderType.ReasonixCli=>"reasonix"// 托管的 CLI 参数ManagedCliParameterKeysByProvider[AIProviderType.ReasonixCli]=["binary","effort","budgetUsd","transcriptPath","enableYolo","arguments","startupTimeoutMs"];// 托管的模型参数ManagedModelParameterKeysByProvider[AIProviderType.ReasonixCli]=["model","reasoning"];

在职业目录配置文件main-professions.yaml中:

-Id:"profession-reasonix"Name:"Reasonix"Family:"reasonix"Summary:"hero.professionCopy.primary.reasonix.summary"Icon:"executor-avatar:Reasonix"SourceLabel:"hero.professionCopy.sources.aiProvidersReasonixCli"ProviderType:"ReasonixCli"SortOrder:130DefaultEnabled:trueDefaultParameters:binary:"reasonix"effort:"medium"enableYolo:"false"startupTimeoutMs:"15000"

这样配置后,用户就可以在 Hero 配置界面看到 Reasonix 选项,并进行个性化设置。就像给一个人登记户口,有了身份,才能在这个社会里正常生活。

前端实现细节

前端实现主要负责用户交互和展示,同样分为几个关键部分。

类型生成和视觉映射

首先需要重新生成 OpenAPI 类型:

npmrun generate:api:once

这会生成包含REASONIX_CLI = 'ReasonixCli'的类型定义。然后在视觉映射中:

// executorTypeAdapter.tsexporttypeExecutorVisualType='Claude'|'Codex'|'Copilot'|'Reasonix'|...;exportconstresolveExecutorVisualTypeFromProviderType=(providerType:PCode_Models_AIProviderType):ExecutorVisualType=>{switch(providerType){// ... 其他 casecasePCode_Models_AIProviderType.REASONIX_CLI:return'Reasonix';}};

这样 Reasonix 就有自己的视觉类型,可以显示对应的图标和样式。就像每个人都有自己的身份证照片。

配置表单实现

HeroCliEquipmentForm.tsx中,我们为 Reasonix 添加了专门的配置表单:

casePCode_Models_AIProviderType.REASONIX_CLI:return(<><Form.Item name="binary"><Input/></Form.Item><Form.Item name="effort"><Select><Select.Option value="none">None</Select.Option><Select.Option value="low">Low</Select.Option><Select.Option value="medium">Medium</Select.Option><Select.Option value="high">High</Select.Option></Select></Form.Item><Form.Item name="budgetUsd"><InputNumber/></Form.Item><Form.Item name="transcriptPath"><Input/></Form.Item><Form.Item name="enableYolo"><Switch/></Form.Item><Form.Item name="arguments"><Input/></Form.Item><Form.Item name="startupTimeoutMs"><InputNumber/></Form.Item></>);

这个表单涵盖了所有 Reasonix 支持的参数,用户可以根据自己的需求进行配置。就像给一个人量身定做衣服,合身最重要。

多语言支持

为了让国际用户也能使用,我们添加了多语言支持:

# locales/*/common/hero.ymlprofession:primary:reasonix:name:"Reasonix"summary:"基于 ACP 的 AI 代码助手"parameters:effort:"计算力投入"budgetUsd:"预算 (USD)"transcriptPath:"转录文件路径"enableYolo:"启用 YOLO 模式"

毕竟语言不通,再好的东西也没法用。

健康监控映射

前端还需要展示 Reasonix 的健康状态:

// healthApi.tsexportconstMONITORING_CHANNEL_FALLBACKS={// ... 其他 providerreasonix:{displayName:'Reasonix',icon:'executor-avatar:Reasonix'}};exportconstmapProviderTypeToMonitoringCliId=(providerType:PCode_Models_AIProviderType):string=>{switch(providerType){// ... 其他 casecasePCode_Models_AIProviderType.REASONIX_CLI:return'reasonix';}};

这样用户可以在监控面板中看到 Reasonix 的状态,如果 CLI 未安装或不可用,会得到清晰的提示。就像医生给病人检查,有问题早发现早治疗。

最佳实践和注意事项

在实现过程中,我们总结了一些最佳实践和需要注意的地方。

参数验证

ReasonixCliProvider 必须严格验证配置参数,拒绝不支持的设置键:

publicvoidValidateConfigurationOverrides(Dictionary<string,string?>overrides){foreach(varkeyinoverrides.Keys){if(!SupportedSettingKeys.Contains(key)){thrownewHeroProviderConfigurationException($"Unsupported setting key '{key}' for Reasonix provider");}}}

这样可以防止用户配置错误的参数,避免运行时错误。就像守门员,不能让不该进的东西混进来。

会话绑定管理

使用ConcurrentDictionary管理会话绑定,支持会话恢复:

_sessionBindings[cessionId]=sessionId;// 在后续请求中绑定已存在的会话if(_sessionBindings.TryGetValue(cessionId,outvarboundSessionId)){options.SessionId=boundSessionId;}

这种设计让用户可以在中断后恢复之前的会话,提供更好的体验。就像把一个故事记住,下次还能继续讲。

优雅降级处理

前端应该检查 CLI 可用性,并给出友好的提示:

constreasonixAvailable=awaithealthApi.checkCliAvailable('reasonix');if(!reasonixAvailable){showMessage('Reasonix CLI 未安装,请在系统 PATH 中配置');}

不要让用户遇到莫名其妙的错误,提前检查并给出明确的指导。毕竟谁也不愿意莫名其妙地被卡住。

测试覆盖

完善的测试是质量保证的关键:

[Fact]publicasyncTaskExecuteCommandStreamAsync_WithValidCommand_StreamsReasonixResponse(){// Arrangevargrain=_grainFactory.GetGrain<IReasonixGrain>("test-cession");varresponses=newList<ReasonixResponse>();// Actawaitforeach(varresponseingrain.ExecuteCommandStreamAsync("help")){responses.Add(response);}// Assertresponses.Should().NotBeEmpty();responses.All(r=>r.Kind==ExecutorResponseKind.Content).Should().BeTrue();}

这样的单元测试可以验证核心功能是否正常工作,防止回归错误。就像考试前做练习题,总得确保自己真的掌握了。

总结

通过这次 Reasonix 的集成实践,我们成功地将一个本地 CLI 工具提升为系统的一等 Agent Provider。整个过程中,我们遵循了既定的架构模式,做出了合理的技术决策,最终实现了一个功能完整、用户体验良好的集成方案。

这套方案的核心价值在于:

  1. 清晰的三层架构分离了关注点,降低了复杂度
  2. 专用 Grain 和 thin adapter 的设计保持了灵活性
  3. 优雅降级和健康监控提升了用户体验
  4. 完善的参数验证和会话管理保证了可靠性

对于其他类似 CLI Provider 的集成,这套方案提供了可复用的模式。我们希望这次实践能够帮助到其他开发者,也欢迎大家到 HagiCode 项目中交流经验。

其实很多事情都是这样,一开始看着难,但只要方法对了,一步一步来,总能解决的。就像登山,看着山顶很远,但只要不放弃,总能爬上去。

总结

回到“从零开始:如何将 Reasonix CLI 集成到 HagiCode 系统中”这个主题,真正值得反复确认的不是零散技巧,而是约束条件、实现边界和工程取舍是否已经看清。

只要把文中的判断依据沉淀成稳定的检查项,后续面对类似问题时就能更快做出可靠决策。

原文与版权说明

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

  • 本文作者: newbe36524
  • 原文链接: https://docs.hagicode.com/go?platform=csdn&target=%2Fblog%2F2026-06-09-integrating-reasonix-cli-into-hagicode%2F
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
http://www.zskr.cn/news/1497855.html

相关文章:

  • 终极指南:如何免费解锁Steam游戏成就的完整解决方案
  • 郑州家电维修平台推荐:本地用户反馈较多的几家服务商(2026最新发布) - 欧米到家
  • 郑州婚纱照哪家好?2026深度解析行业趋势与优质机构选择指南 - 品牌评测官
  • Gartner发布创新洞察:AI SOC智能体加速通信运营商安全运营转型
  • 中医无需神化,也无需黑化——AI时代的理性态度
  • 机器人DSP如何精准选型:三大痛点下的国产芯片实力排名
  • 南京家电维修平台推荐:本地用户反馈较多的几家服务商(2026最新发布) - 欧米到家
  • Keyboard Chatter Blocker:拯救机械键盘的终极防抖方案
  • 靠谱的昆明汽车维修机构 - 英特菲斯
  • AI 驱动的组件测试生成:从 DOM 快照到智能断言的工程实践
  • 巴斯夫地坪施工与材料代理一站式服务:为什么选择只做一家的施工商?——港珠澳大桥人工岛地坪施工商 - 热点速览
  • Steam成就管理终极指南:3分钟掌握免费成就解锁与重置技巧
  • 2026最新GEO排名优化监控测评:主流GEO平台功能解析与效果验证 - 新闻快传
  • 2026年自动化码垛包装设备选购指南:立柱码垛机、码垛机械手、纸箱码垛、非标码垛设备厂家选择指南,产能、工艺、品控三维度客观解析 - 海棠依旧大
  • 六月,全国开票编码全面升级后,以下六种发票将被拒收
  • 29、【python】信息管理系统
  • 2026 浙江工厂厂区景观设计施工优质企业排行榜 杭州美村美户凭实力成为首选 - 玖叁鹿
  • 2026 遵化厨卫屋面地下室漏水瓷砖空鼓测评:吉修匠 99.8 分五星榜首 - 吉修匠
  • 2026年合肥理工学校怎么样?有什么专业? - cc江江
  • 2026年生成式AI接口调度服务生产环境实测:中大型企业高可用基础设施选型参考
  • 16.4完整可运行代码:使用 SummarizationMiddleware 管理长对话记忆
  • 好用的昆明宝马专修哪家 - 英特菲斯
  • 从 SQL 美化工具到智能自动补全:开发者生产力工具的发展史
  • 2026年防火涂料品牌综合实力榜:陕川正途领衔,六大防火材料优选 - 深度智识库
  • 2026企业办公家具采购:群兴俊达家具直供解决成本效率痛点 - 热点速览
  • 破包率从2.5%降至0.2%:吸嘴袋厂家案例解析 - 热点速览
  • 9大网盘高速下载终极方案:LinkSwift直链解析工具完全指南
  • AI外贸培训哪家课程好
  • 佛山二手车买卖公司排行:合规与服务实力大盘点 - 奔跑123
  • 【WorkBuddy专栏17】一个 AI 不够用?WorkBuddy SubAgent 多智能体协作系统深度拆解