记首次 .NET 跨平台开发——Deepseek Harness Desktop
史上增长最快的开源 Agent 框架 DeepSeek Harness(DSH)给我带来了 DIY 的乐趣。官方给的"命令行 + 网页"这套组合能用,但不方便用。我决定给它做个桌面客户端 dsh-ng-desktop:点击即开、托盘常驻、开机自启,界面直接内嵌原来的 Web 页面。
此前我就想体验.NET + Avalonia 开发桌面软件,这是一个很好的尝试契机,Avalonia 主打跨平台,配合 Native AOT 还能编译出精简安装包。我脑子里默认了一个等式:
优雅的语言 + 跨平台框架 + 智能体 = 高效的组合。
实践证明,这个等式所忽略的,是大语言模型这个超级做题家碰上冷门出题时的幻觉。
一个暴论和三个原因
一句话:
在 AI 编程的时代,用 Avalonia 做跨平台客户端并不合适;.NET 可能更适合服务端,Avalonia 可能更适合从传统 WPF 迁移的项目。
这里针对的是"AI 开发跨平台客户端"的具体场景,框架有它擅长的领域,关键变量也不是语言,而是有多少公开语料、生态里有多少现成的轮子。
在细节上踩坑多了,这些得到验证:
一、数据飞轮:AI 擅长"热门",“冷门”容易出错
模型的训练数据,大量来自开源项目、社区问答和公开代码。像 TypeScript、Python、Go 这些开源世界的绝对主流,语料浩如烟海,模型对它们的常见写法和最佳实践了如指掌。而那些偏企业级的组合,语料就稀疏得多。
我用的这套 .NET + Avalonia + Native AOT + macOS + WebKit 冷门度是相乘的。AI 面对它时没有多少现成经验可抄,就容易"想当然":忽略平台差异、套用它在别的栈里的直觉、犯一些很低级的错误。我换过好几个模型,结论都一样:不是模型不行,是语料密度不够。样例越少,幻觉率越高。
二、框架与平台不完善:生态需要解决的问题被我碰上了
跨平台框架存在的意义,本该是替开发者挡住平台差异。但真做下来,Avalonia 和 .NET 在这件事上的抽象并不完整,不少本该由框架或生态兜底的细节,直接漏到了我手上。
举两个例子。一个是 WebView 的数据清理:Avalonia 没给现成接口,只能额外写个 Objective-C 辅助程序去清 WebKit 的数据。另一个是单实例:客户端要保证只开一个,用 .NET 的命名管道实现,结果在 macOS 上它被映射成系统域套接字,路径有个 104 个字符的长度上限,GitHub Actions 的临时目录路径一长就直接溢出。
这些是框架没帮你做,你碰上了就得去调研和验证一堆本不该你操心的平台细节。
三、成熟方案缺失:没有现成库,只能自己摸索实现
热门生态里,很多坑早被人踩过、封装成了库。比如 macOS 下 GUI 程序从 Finder 启动时拿不到用户的 shell 环境变量、找不到 Node——这在 Node 生态里有 fix-path 这类现成库,一行就能解决。但在这个生态里没有,只能自己实现一段扫描逻辑,去 nvm、volta、fnm、asdf 各种版本管理器的目录里一个个翻。
遇到问题找不到直接可用的库,只能自己从头写;自己写,就意味着边界情况和平台差异全都自己扛。
信心与成本决定开发体验
当智能体花了十几分钟乃至几十分钟调研仍卡在一个步骤上的时候,看到状态栏里的套餐额度在以肉眼可见的速度减少,这是很影响开发体验的。
信心,来自两件事:出错少不少、能不能一次成。最影响体验的是低级错误,冷门栈里,AI 很容易写出"看着对、实际错"的代码。最典型的一次:为了在 macOS 上正确拉起和关闭子进程,智能体写了系统底层调用,结果把一个"按地址传参"写成了"按值传参"。这个错在 Windows 上根本不暴露,一到 macOS 上程序直接崩溃。够低级,也够致命,正是冷门组合下 AI"想当然"的典型。
成本,说的是为定位和验证这些细节花的力气。为省事,我只在 Windows 上开发,macOS 的问题推到 GitHub Actions 的 Apple Silicon runner 上跑,结果反而费事,改一次、等一次、崩一次、再改一次。翻了下记录,从 0.9.11 到 0.9.19 连续九个版本,几乎全在跟 macOS 的兼容问题较劲。为了定位那个崩溃,还专门在 CI 里加了崩溃转储的自动分析。真正耗时间的从来不是写功能,是这些细节的反复验证。
.NET 与 Avalonia 也有它做得好的地方
为避免单方面控诉。公平地说,这套栈也有长处。
- 编译期防线:可空引用类型、"警告即错误"、最新的代码分析器,能把一大类风险在编译期拦住,而不是像解释型语言那样等到运行时才炸。
- AOT 分析器前置排雷:Native AOT 虽冷门,但 .NET 提供 AOT/裁剪分析器,会在编译期提示"这段代码 AOT 不兼容"。
- 单文件自包含分发:免装运行时的单文件,体积和资源占用比"每个应用捆一套浏览器内核"的方案强。
- 强类型建模:清晰的类型边界、贯穿全程的异步取消,让代码结构足够工整。
但这里有个微妙的地方:这些长处,几乎全都服务于"有经验、愿意手搓、读得懂编译器诊断的人类开发者"。而 AI 辅助编程要的正好相反——大量能借鉴的语料、唾手可得的轮子。所以问题不在谁强谁弱,而在强项用错了场景:在一个靠 AI 大量生成代码、又指望生态兜底的场景里,这套栈的长处使不上劲,短处却被放大。反过来,别的平台也有自己的坑——体积、内存、弱类型的运行时错误——只是通常有更成熟的生态替你兜着。
经验教训
- 冷门度会相乘:评估选型要看「框架 × 运行时模式 × 目标平台 × 第三方组件」的冷门乘积,而不是只看框架本身。
- AI 的"想当然"与语料密度成正比:冷门组合语料趋零、幻觉率高;换模型解决不了,换栈才能解决。
- 跨平台是 API 级承诺,不是语义级承诺:同一套 API 在不同平台语义可能不同,"在 Windows 上跑通"不等于"跨平台完成"。
- 抽象泄漏到原生层,就是换栈的信号:当你被迫手写系统级原生调用、或额外写一段原生辅助程序时,说明框架的抽象不完整,成本开始失控。
- 冷门栈反而要求你更懂底层,热门栈允许你不懂——因为生态已经替你懂了,那些现成库的存在就是"这个坑已被封装"的证明。
- 验证成本是隐形的成本大头:本地复现不了目标平台的问题时,"改 → 等 → 崩 → 改"的低效循环会放大一切痛苦。
留待想象
DeepSeek Harness 的论文宣称发明了一种新的编程范式,AI带来的范式还会不断创新,本篇可以视为一种吐槽,没什么一定的结论。
如果能搭建起跨设备、平台、框架的Loop Engineering,让智能体拿着第一手信息自己闭环——查资料、做实验、跑验证,要什么自己实现,模型强到自己补完生态,那"语料少"这个约束会被削弱,性能、类型等基础优势反而会凸显。
就现阶段而言,兴趣是第一驱动力,也是没有更好,只有更适合。
评论