Table of Contents
今天我在服务器上把 DeepSeek Harness(DSH)升级到了最新的 0.2.1-rc.2。升级过程本身挺顺利,但服务跑起来之后很快碰到了一个现实问题:我一直在用的 dsh-public-access 插件失效,没法正常登录了。
我的 DSH 部署在远端服务器上,平时要通过公网或局域网访问,全靠这个插件在前面挡一层用户名和密码认证。插件一罢工,服务虽然还在后台跑着,但实际上已经进不去了。出问题的原因也不复杂,原插件主要针对 0.1.x 版本开发,而 DSH 还在 Developer Preview 阶段,官方早就提醒过会有破坏兼容性的改动。到了 0.2.1 版本,底层的 Web 鉴权、连接入口和 Host 校验机制都变了不少,而且迭代节奏极快——仅 10 月 17 日同一天就先后发了 rc.1 和 rc.2,其中 rc.1 还专门加上了插件版本兼容检查,顺带在管理页里放了一个“让 Agent 创建插件”的入口。
搁在以前,碰到这种上游升级把第三方插件搞挂的情况,无非就是几条路:要么先把 DSH 降级回旧版,要么去 GitHub 提个 Issue 等原作者更新,实在等不及就只能自己把源码拉下来慢慢啃。那天我换了个做法,直接把原项目 fork 到自己的 GitHub 仓库,然后让 DeepSeek Harness 同时去读旧插件的代码和新版 DSH 的实现,自己把兼容层面的改动做完。
翻看了一下 Git 提交记录,从同步上游的 1.3.0 版本,到完成 0.2.1-rc.2 的主要适配,前后花了不到半个小时。期间它顺着新版的变化,把鉴权入口、Host/Origin 栅栏、public-url 和 TLS 相关的逻辑改了一遍,还顺手补上了 21 个单元测试。我把改好的包发布到自己的 npm 账号下,回到服务器上替换掉旧插件,登录界面就恢复正常了。折腾完这一趟,我倒没怎么感慨 AI 写代码有多快,反而注意到一个角色上的变化:半个小时前我还只是这个插件的普通用户,半个小时后,我已经发了自己的包,开始维护一个自己的分支了。
Fork 从来不难,难的是 Fork 以后怎么办
开源软件一直给用户留着最大的自由度:代码就摆在那里,用着不满意可以自己改,作者不维护了也可以随时 Fork。所以如果单把这件事看成“AI 帮用户改了开源代码”,其实谈不上什么新意,毕竟在 GitHub 上点一下 Fork 按钮本来就只需要一秒钟。
真正让人犯怵的,一直是点完 Fork 之后的那一长串麻烦事。拿到一份陌生的代码,你得先搞清楚原作者是怎么设计的,它依赖了上游系统的哪些行为,上游升级之后哪些接口废弃了、哪些换了位置;等好不容易把代码改通了,还得跑测试、发包,更头疼的是从这一刻起你的代码就和上游分叉了,下次主程序再升级,同样的事情还得再来一遍。对企业研发团队来说,这意味着持续的人力投入;对个人开发者来说,搭进去的就是实打实的业余时间。所以绝大多数时候,哪怕开源协议赋予了任何人修改和接管的权利,大家遇到问题还是只能选择等原作者更新——说白了,维护这件事太贵了。
而开源生态的另一面,恰恰是维护力量的捉襟见肘。GitHub 近期引用过一项针对 500 多名开源维护者的调查,里面提到大约三分之一的开源项目完全由单人维护,接近四分之三的项目维护者不超过三个人。我们平时在生产环境里习以为常的很多基础组件和周边工具,背后往往就靠一两个开发者用业余时间撑着。当上游主项目像 DSH 这样一天连发两个 RC 版本时,周边的小插件跟不上节奏再正常不过了。
AI 开始降低“接管陌生代码”的成本
过去两年大家聊 AI Coding,最常见的场景还是从零开始写代码:给它一段需求,让它生成一个前端页面、一个 API 接口或者一段复杂的 SQL。这类用法我自己平时也一直在用,它解决的是“怎么把代码写得更快”。
但这次改插件的体验不太一样。我并没有让它从头写一个登录插件,而是丢给它两个已经存在、且都不是我写的系统:一边是别人的 dsh-public-access,另一边是刚刚重构过的 DeepSeek Harness。在这种跨版本迁移的任务里,最后把那几十行修改敲进编辑器根本不费什么工夫,真正耗时的是前期的阅读和比对——得先在旧插件里顺藤摸瓜,看它调了 0.1.x 的哪些内部接口,再去 0.2.1 的代码库里翻找这些行为被挪到了哪里、新增了什么校验规则。
这恰恰是现在的 Coding Agent 和早期代码补全工具拉开差距的地方。它可以跨文件甚至跨仓库检索,顺着调用链去读上游实现,改完多个文件后自己跑一遍测试看能不能过。DeepSeek Harness 这次在插件管理页里直接加上“让 Agent 创建插件”的入口,其实也是在把这种工作流变成正式的产品能力。当阅读和摸清一个陌生项目的成本被大幅压低之后,AI Coding 带来的变化就不再局限于帮程序员写好手头的新需求,它还让接管别人留下的旧代码变得便宜了许多。
“作者不更新怎么办”,开始多出一种选择
以前一个开源依赖停更或者跟不上版本,摆在使用者面前的选择非常有限:要么忍着不升级,要么换一套替代方案,再不然就得专门抽调工程师把代码接过来。现在,保留原项目、自己维护一个只解决当前环境问题的私有 Fork,开始变成一条算得过账来的路子。
当然,这并不意味着以后每个人都会去维护一套自己的 Linux 内核或者数据库。大型基础软件涉及复杂的架构演进、安全响应和社区协同,不会因为大模型会写代码就突然变得简单。最先发生松动的,反而是大量的插件、SDK、适配器、CLI 和内部胶水工具。这类项目通常代码规模不大,功能边界也很清楚,绝大多数兼容性问题都出在上下游接口的变动上。过去为了这么一个小工具专门搭进去一个工程师的精力,投入产出比往往划不来;但如果 Agent 能先把繁琐的代码阅读、接口比对和基础测试干掉七八成,“自己动手维护一版”的门槛就一下子降下来了。
我这次碰到的情况就是一个很典型的缩影。dsh-public-access 的原作者还在,项目也远没到废弃的地步,纯粹是因为 DSH 最近迭代太猛,原有的适配暂时没跟上我的升级节奏。放在现在,我不需要干等着社区先磨合出一个统一的新版本,完全可以先把自己服务器上卡住的那一段补上。如果这种做法越来越普遍,开源生态里“用户”和“维护者”的界限大概会变得比以前模糊得多——平时大家只是拿来即用的用户,但当某个依赖真正卡住自己的生产环境时,随时可以临时切换成自己那个分支的维护者。
代码可以交给 AI,结果还得有人负责
不过,那半个小时的适配做完之后,事情其实还没有彻底结束。等我把第一版插件部署到服务器上实际登录时,发现页面直接返回了 405 错误:登录表单因为一个相对路径处理的问题,把提交地址拼成了 /_auth/_auth/login。那 21 个单元测试之所以没拦住这个问题,是因为单测只验证了模块内部的逻辑,没覆盖到浏览器端完整的路径跳转。我只好回来让 Agent 重新定位路径拼接的逻辑,改完再补上对应的测试,最后发布了 2.1.1 版本才算真正跑通。
这个小插曲也给我提了个醒:AI 能把代码改出来、能把单测跑绿,跟这段代码已经可以放心地丢进生产环境,完全是两码事。尤其是像 dsh-public-access 这样直接管着公网入口和身份认证的插件,一旦改出纰漏,代价可不只是页面打不开,搞不好还会把原本该拦住的端口暴露出去。到底哪些接口允许放行、哪些鉴权逻辑一步都不能省、测试用例有没有覆盖真实的访问路径、打出来的包敢不敢往线上发,到了最后一步,还是得由懂业务和架构的人来做判断、担责任。
所以哪怕生成和修改代码变得越来越便宜,开源维护者本身依然不可替代。这两年 GitHub 社区一直在讨论维护者倦怠(maintainer burnout)和开源可持续性的问题,正是因为长期维护一个项目本来就是一件极其琐碎、需要持续做判断和兜底的苦差事。AI 能帮人省掉大量啃陌生代码、写样板测试的体力活,但它替不了背后的那份责任。
回头看这次升级插曲,如果只把它当成又一个“AI 半小时修好插件”的效率故事,其实没什么意思。真正让我有所触动的是,过去开源协议虽然在规则上给了每个人修改代码的自由,但高昂的阅读和维护成本,实际上把大多数普通用户挡在了门外。现在这层门槛正在被慢慢抹平。至少对有一定技术判断力的人来说,以后再碰到“这个项目的作者什么时候更新”的问题,除了去 Issue 区催更和等待,手里总算多了一个以前很少认真考虑的选项:如果我的系统真的依赖它,那不如先让 AI 帮我把自己的那个版本维护起来。
我只是想修一个DSH插件,半小时后却成了它的维护者 Share on X