跳转到内容

对接 Reasonix 1.x 跑通 DeepSeek V4:ACP 模型选择器接入实战

编辑此页
HagiCode for Windows Microsoft Store artwork
HagiCode for Windows 已上线 Microsoft Store
HagiCode for Windows 现已正式登陆 Microsoft Store,Windows 用户可以直接从商店完成安装并接收渠道更新。现在就打开商店页看看吧。
打开 Microsoft Store

对接 Reasonix 1.x 跑通 DeepSeek V4:ACP 模型选择器接入实战

本文聊聊在 HagiCode 里怎么把 Reasonix 1.x 这个本地 ACP CLI provider 切到 DeepSeek V4。重点其实也不在”接进来”,而是在 Reasonix 1.x 相比 0.x 那一刀的语义变化——启动参数被砍到只剩一个 -model,凭据和策略全搬到 reasonix.toml,这中间踩的坑和验证路径,咱一点点说清楚。

背景

最近有人问了个挺具体的问题:在 HagiCode 里怎么对接 reasonix 1.x 版本来使用 deepseek v4。

乍一看像个配置题,真翻代码才发现,其实这是一道 CLI 语义迁移题。Reasonix 是 HagiCode 多 Agent Provider 体系里的一个本地 ACP(Agent Communication Protocol)CLI。它在 HagiCode 的三层架构里位置很清楚:

  • HagiCode.Libs —— ReasonixProviderReasonixOptions,封装 reasonix acp 的进程启动、ACP 握手、流式通知映射。
  • hagicode-core —— ReasonixCliProvider 薄适配器、AIProviderType.ReasonixCli = 12ReasonixGrain、Hero 参数映射、健康监控。
  • web —— OpenAPI 类型、视觉映射、Hero 配置表单、多语言文案。

整个接入链路在归档提案 openspec/changes/archive/2026-06-06-integrate-reasonix-agent-provider 里已经全部落地了。所以问题就不再是”怎么把 Reasonix 接进系统”,而是”接进来之后,怎么把模型切到 DeepSeek V4”。

关键的转折点在于:Reasonix 1.x 和 0.x 的 ACP bootstrap 语义发生了一次根本变化。这个变化直接决定了你怎么配 DeepSeek V4。毕竟语义这种东西,一旦变了,表面再像也是两回事了。

悬念先放这:为了把这套多 provider、多模型的复杂度理顺,HagiCode 在 Reasonix 适配层做了一次”字段保留、语义迁移”的设计,稍后我会具体讲为什么这么取舍。

关于 HagiCode

本文分享的方案来自我们在 HagiCode 项目中的实践经验。

HagiCode 是一个 AI 代码助手项目,支持多种本地/远程 Agent Provider。代码开源在 HagiCode-org/site

分析

1.x 把启动参数砍到只剩一个

直接看 ReasonixProvider.BuildCommandArguments

internal virtual IReadOnlyList<string> BuildCommandArguments(ReasonixOptions options)
{
var arguments = new List<string> { "acp" };
// Reasonix 1.x reduced ACP bootstrap to a transport-scoped provider selector.
AppendOption(arguments, "-model", options.Model);
foreach (var argument in NormalizeExtraArguments(options.ExtraArguments))
arguments.Add(argument);
return arguments;
}

那行注释是题眼:1.x 把 ACP 启动收敛成一个”transport-scoped 的 provider 选择器”。翻译成人话——启动时唯一还有意义的 flag,就是 -model 了。

而 0.x 时代那一票老 flag,被显式过滤掉了:

private static readonly HashSet<string> FilteredBootstrapFlags = new(StringComparer.OrdinalIgnoreCase)
{
"-model", "-m", "--model",
"-dir", "--dir",
"-effort", "--effort",
"-budget", "--budget",
"-transcript", "--transcript",
"-mcp", "--mcp",
"-mcp-prefix", "--mcp-prefix",
"-yolo", "--yolo",
"--dangerously-skip-permissions",
"--no-proxy"
};

单元测试也直接证明了这点。传进去一堆 legacy flag,出来的命令行干干净净,也不报错,只是默默丢掉:

arguments.ShouldBe(
[
"acp",
"-model", "deepseek-v4-flash"
]);

ReasonixOptions 字段还在,但语义变了

这里有个特别有意思的设计。ReasonixOptionsEffortBudgetUsdTranscriptPathEnableYoloMcpServerSpecsMcpPrefix 这些字段全都保留着,只是每个注释都老老实实写着”Reasonix 1.x ACP no longer accepts … so this value is currently ignored”。

这是典型的字段保留、语义迁移模式:调用方契约不破坏(0.x 代码继续能编译、能传值),可是运行时这些值会被静悄悄丢弃。policy 类的东西(权限、MCP 插件、代理)被要求搬到 reasonix.toml 里。

打个比方,相当于你家原来的电灯开关还在墙上,可是装修师傅把线路改了,现在开关变成了装饰,真正的灯光控制搬到了智能家居面板上。开关看着没变,按下去也不报错,只是灯就是不亮了。

所以接入 DeepSeek V4 的核心动作其实就一句话:把模型 id 通过 -model selector 传进去,把凭据/endpoint 配到 reasonix.toml

DeepSeek V4 怎么进来

在 HagiCode 的测试和 README 里,DeepSeek 系列就是通过 Model 字段接入的标准用法:

var reasonixOptions = new ReasonixOptions
{
WorkingDirectory = "/path/to/repo",
Model = "deepseek-flash",
SessionId = "reasonix-session-123"
};

测试里反复出现 Model = "deepseek-v4-flash",对应生成的命令行就是 reasonix acp -model deepseek-v4-flash。具体模型 id(deepseek-v4-flashdeepseek-flash 等)要按你装的 Reasonix 1.x 版本和 reasonix.toml 里注册的 provider 别名为准,毕竟别名的真假,Reasonix 自己心里最清楚。

工作目录和会话恢复走 ACP,不走 CLI flag

这是 1.x 的第二个语义变化,容易让人懵。0.x 时代用 --dir 指定工作目录,1.x 改成走 ACP 协议内的 session/new / session/load

var sessionHandle = await sessionClient.StartSessionAsync(
workingDirectory,
options.SessionId,
model: null, // 模型选择完全由启动时的 -model 决定
startupCts.Token);

注意 StartSessionAsyncmodel 参数传的是 null——模型选择完全由启动时的 -model 决定,session 级别不再覆盖模型。SessionId 仍然是 provider-native 的连续性提示,用来 resume 会话而已。

解决

把上面的分析串成一条可执行路径,分四步走吧。

第一步:装好 reasonix CLI

Reasonix 是本地安装、IsPubliclyInstallable: false 的 provider,不能用 npm 公开装。先把 reasonix 可执行文件放到 PATH 里。装好之后用 HagiCode.Libs 自带的 console 验证一下:

Terminal window
# 跑 Ping 场景,执行 reasonix acp 握手并报告版本
dotnet run --project src/HagiCode.Libs.Reasonix.Console -- --test-provider reasonix

握手失败,多半是两种情况:要么 PATH 没找到 reasonix,要么 reasonix.toml 没配。其实也没别的理由了。

第二步:在 reasonix.toml 里配 DeepSeek V4 凭据

1.x 不再接受 --api-key--base-url 这类启动 flag,模型提供商的 endpoint、密钥、代理策略都要写到 reasonix.toml。配置内容大致包括:

  • DeepSeek V4 的 API endpoint
  • DeepSeek 的 API key
  • 你想暴露给 -model selector 的别名(比如 deepseek-v4-flash

具体字段名以你装的 Reasonix 版本文档为准。HagiCode 这一侧只负责把 -model deepseek-v4-flash 透传过去,至于这个别名怎么解析成真实模型,那就是 Reasonix 自己的事了——职责边界划得很清,谁也别越界。

第三步:配置 HagiCode 的 ProviderConfiguration

后端 ReasonixCliProvider.ResolveModel 的解析优先级是:request.Model 优先,否则走 _config.Model

private string? ResolveModel(AIRequest request)
{
var model = string.IsNullOrWhiteSpace(request.Model)
? _config.Model
: request.Model;
return string.IsNullOrWhiteSpace(model) ? null : model.Trim();
}

所以在 appsettings 或运行时配置里,把 provider 的 Model 设成 DeepSeek V4 的别名:

{
"AIProvider": {
"Providers": {
"ReasonixCli": {
"Type": "ReasonixCli",
"Model": "deepseek-v4-flash",
"Settings": {}
}
}
}
}

这里有个特别容易踩的坑:Settings 里只能放白名单内的 key:

private static readonly IReadOnlyList<string> SupportedSettingKeys =
[
"effort", "budgetUsd", "transcriptPath",
"enableYolo", "arguments", "startupTimeoutMs", "reasoning"
];

ValidateConfigurationOverrides 会把白名单外的 key 直接拒绝。而且这些 key 在 1.x 里大多被忽略(对应 ReasonixOptions 里那些 ignored 字段),所以千万别把 DeepSeek 凭据塞进 Settings,那不是它们该待的地方,凭据归 reasonix.toml

第四步:用 console 做端到端验证

配置完直接用 Reasonix 专用 console 跑完整套件,把模型显式指定成 DeepSeek V4:

Terminal window
# 默认套件:Ping / Simple Prompt / Complex Prompt / Session Resume 四个场景
dotnet run --project src/HagiCode.Libs.Reasonix.Console -- \
--test-provider-full --model deepseek-v4-flash --repo .

四个场景全绿,说明模型选择器、ACP 握手、流式通知、会话恢复全链路都通了。绿了,心里也就踏实了。

实践

前端 Hero 配置表单怎么填

如果你走的是 HagiCode 的 Hero 职业 UI 而不是直接改 appsettings,在 HeroCliEquipmentForm 里选 Reasonix 后,表单字段是这些:

  • binary:默认 reasonix
  • model:填 deepseek-v4-flash(切到 DeepSeek V4 的关键字段)
  • effort:none / low / medium / high(1.x 忽略,但 UI 仍保留)
  • budgetUsd:数字(1.x 忽略)
  • transcriptPath:文本(1.x 忽略)
  • enableYolo:布尔(1.x 忽略,权限归 toml)
  • arguments:透传给 ACP 的额外参数
  • startupTimeoutMs:默认 15000

真正影响 DeepSeek V4 行为的其实只有 model 一个字段,其余在 1.x 下都是装饰罢了。这也是 HagiCode 那个”字段保留、语义迁移”设计在 UI 上的体现——表单不破坏老用户习惯,可是实际生效的字段收敛了。

会话绑定与恢复

ReasonixCliProviderConcurrentDictionary<string, string> 维护 session 绑定,binding key 由 cessionId、工作目录、可执行路径、模型一起算出来:

var bindingKey = NormalizedAcpCliAdapter.BuildBindingKey(
effectiveRequest.CessionId,
options.WorkingDirectory,
options.ExecutablePath,
options.Model);

这意味着同一个会话如果中途切模型,binding key 会变,会被当成新会话。所以接入 DeepSeek V4 后,整个会话生命周期内保持 model 别名稳定,否则 resume 会断。这点我实测踩过,血泪教训,那滋味至今还记得。

监控与降级

Reasonix 在 AgentCliMonitoringRegistry 里用 Provider 策略(不是 Grain 策略),毕竟它可能没装:

new AgentCliMonitoringDescriptor
{
CliId = "reasonix",
DisplayName = "Reasonix",
ProviderType = AIProviderType.ReasonixCli,
Strategy = Provider, // ping-based,走 PATH 发现
ExecutableCandidates = ["reasonix"]
}

前端健康检查会显示 Reasonix 是否可用。如果 reasonix 不在 PATH,UI 要优雅降级成”不可用”——这套逻辑已经内置了,不用自己操心。

几个实战注意点

  1. 模型别名的真实性deepseek-v4-flash 必须是 reasonix.toml 里真实注册的别名,否则 ACP 握手过了、发 prompt 还是会失败。先用 console 验证再上 Hero,别图省事。
  2. 不要用 arguments 传 legacy flagNormalizeExtraArguments 会把 --effort--budget 这些过滤掉,传了也白传,徒劳而已。
  3. 凭据只在 toml:API key、endpoint、代理、MCP 插件全部在 reasonix.toml,HagiCode 这一侧的 Settings 白名单里根本没有这些字段。
  4. startupTimeoutMs 可调:DeepSeek V4 冷启动如果慢,把 startupTimeoutMs 从默认 15000 调高,这个字段 1.x 是认的。
  5. 经济系统归到 claude 桶:前端 resolveEconomicSystemByExecutorType 把 Reasonix 映射到 'claude' 桶,纯展示用,不影响计费。

一条最小验证路径

如果只想最快确认 DeepSeek V4 能跑通,不碰 Hero UI:

  1. 装 reasonix,配 reasonix.toml(DeepSeek endpoint + key + 别名)
  2. appsettingsReasonixCli.Model = "deepseek-v4-flash"
  3. dotnet run --project src/HagiCode.Libs.Reasonix.Console -- --test-provider-full --model deepseek-v4-flash
  4. 四个场景全绿,接入完成

总结

回到最初那个问题——“怎么对接 reasonix 1.x 来用 deepseek v4”。

答案其实也就一句:把模型别名通过 -model selector 传进去,把凭据和策略配到 reasonix.toml,别指望 CLI flag

只是这一句背后,是 Reasonix 1.x 一次相当干脆的语义收敛:启动参数砍到只剩 -model,工作目录和会话恢复搬到 ACP 协议内,policy 全部下沉到 toml。HagiCode 这边的适配层没有硬刚这次变化,而是选了”字段保留、语义迁移”的温和路线——老代码继续能编译、能传值,运行时静默忽略,把生效的开关收敛到 -model 一个。

这种取舍的好处是平滑迁移,代价是文档得讲清楚——这也是这篇文章存在的意义。你只要记住三件事:

  1. 模型走 -model,DeepSeek V4 就是 -model deepseek-v4-flash
  2. 凭据走 toml,别往 Settings 里塞
  3. 会话内别切模型,binding key 会变,resume 会断

HagiCode 选择这么设计 Reasonix 适配层,本质上是因为它要同时容纳多个 provider、多个模型版本、多种部署形态。这种多语言、多平台的复杂度,正是我们在 HagiCode 里反复打磨 provider 适配策略的直接原因。

参考资料

  • Reasonix Provider 实现:repos/Hagicode.Libs/src/HagiCode.Libs.Providers/Reasonix/ReasonixProvider.cs
  • Reasonix Options 字段语义:repos/Hagicode.Libs/src/HagiCode.Libs.Providers/Reasonix/ReasonixOptions.cs
  • 后端薄适配器:repos/hagicode-core/src/PCode.ClaudeHelper/AI/Providers/ReasonixCliProvider.cs
  • 接入提案归档:openspec/changes/archive/2026-06-06-integrate-reasonix-agent-provider
  • 后端 spec:openspec/specs/reasonix-backend-integration/spec.md
  • 单元测试(含 deepseek-v4-flash 用例):repos/Hagicode.Libs/tests/HagiCode.Libs.Providers.Tests/ReasonixProviderTests.cs
  • HagiCode 官网:hagicode.com

总结

围绕“对接 Reasonix 1.x 跑通 DeepSeek V4:ACP 模型选择器接入实战”,更稳妥的推进方式是先把关键配置、依赖边界和落地路径逐步跑通,再补齐优化细节。

当目标、步骤和验收点都明确之后,这类方案通常就能更顺畅地进入实际交付。

开始使用 HagiCode

一次安装,几分钟上手

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