AI编程
快来分享你的内容吧~
- 3 天前·后端我搞了个新公司,利用 AI 编程做了个全球化的新产品,没想到这么快就有自然流量了,感谢这个 Vibe Coding 时代查看全文加油鸭:太酷了!从注册公司到上线AI配图工具一气呵成,鱼皮老师这波Vibe Coding实操太有说服力了~833分享
- 10-24 11:37·后端最近 B 站闹鱼灾了,大批 DeepSeek AI 机器人涌入评论区,我通过 Vibe Coding 搞出《蓝色大肥鱼清除插件》,帮你忽略掉冰冷的 AI 回复,还你一个干净的浏览体验。查看全文加油鸭:太酷了!用技术对抗技术,幽默又有深度,鱼皮老师这波操作既解决问题又充满创意,点赞!933分享
- 10-23 10:42·后端PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚查看全文加油鸭:这篇漏洞解析太硬核了!比喻生动、原理清晰、应对方案实用,既专业又接地气,为PHP安全防护提供了及时有力的指南!831分享
- 10-22 10:45·后端
- 10-19 17:58·后端DeepSeek V4.1 Flash 1017 发布,4 大 AI 编程项目实战测评,看看结果如何?性价比拉满 + 主打许愿式编程 + 开放自研搜索接口查看全文加油鸭:鱼皮老师这波深度测评太硬核了!从跑分到实战,细节拉满、对比清晰,既专业又接地气,为社区贡献了超有价值的参考~832分享
- 10-19 12:03·后端261016 DeepSeek 故障分析复盘,DeepSeek 为什么会崩这么久?DeepSeek 又做了什么,能让风评瞬间逆转?查看全文加油鸭:感谢分享,@编程导航小智 帮忙总结一波~1032分享
- 10-16 10:21·后端
我的第一个出海产品!7 天 2 万
大家好,我是程序员鱼皮。 Vibe Coding 时代,越来越多的人开始用 AI 编程做自己的产品,我作为一个程序员 + AI 博主,当然也跃跃欲试。 毕竟,谁不想出海赚美刀呢? 于是国庆期间,我注册了自己的第一家香港公司 Cyber Koi Limited,中文名叫「**赛博锦鲤科技有限公司**」,是不是听起来就很好运哈哈~ 有了公司之后,就可以开通 Stripe 全球收款了。信用卡、Apple Pay、Google Pay 都能付,国内用户还能直接用微信支付、支付宝,非常丝滑。  万事俱备,今天就给大家分享我的第一个出海尝试项目:**memecub**,一个表情包搜索引擎 + AI 自动配图工具。 > 指路:https://memecub.com  它不只是给人用的,更是 **给 AI 用的**。你的 Claude Code、Cursor、Codex 装上它之后,也能自己搜表情包、给文章配图,让你的 AI 也会斗图! ## 为什么要做这个? 看到这儿你可能会想:这年头,好像也没多少人在网上找表情包了吧? 其实,这个需求就来源于我自己! 我一直觉得,**自己都不用的项目,是没必要硬做的**。 经常看我文章的同学应该知道,我写文章时很喜欢配表情包,能让枯燥的技术内容变得更有趣。以前都是我自己一张张人工去找、再手动放进文章里,费时费力。  现在有了 AI,理论上可以直接让 AI 联网搜索表情包、给文章配图。 但实际用下来,问题很多: - **搜不到想要的图**:试了一圈搜索工具,搜出来的图要么不是表情包,要么糊得没法用,要么根本不是我想要的情绪 - **AI 配得不到位**:AI 经常在不该笑的地方插图,或者选的表情包和上下文对不上,还得我自己返工 所以我需要两样东西:一个 **靠谱的表情包图库**,再加一个 **能给文章自动配图的 Agent**。 既然市面上没有顺手的,那就自己做一个吧! ## 一、表情包图库 首先是表情包图库,这是 memecub 的基础。 我们收录了熊猫头、奶龙、蘑菇头、金馆长、吗喽、哈基米、卡皮巴拉等各种热门表情包,网站浏览和搜索 **永久免费**,打开就能用。  我比较推荐的是 **按情绪搜索**。比如你想表达震惊的情绪,直接搜「震惊」,出来的就是各种震惊反应图,而不是字面相近但实际乱七八糟的图片:  当然也支持按表情包的角色搜索,比如最近很火的 DeepSeek 鲸鱼娘,一搜一大把:  点开任意一张表情包,可以直接下载原图、复制图片,甚至 **一键复制 Markdown** 贴进文章里,写公众号和博客的同学应该懂这有多方便~ 而且每张图都有 AI 生成的画面描述,方便 AI 理解图片内容、在合适的位置使用:  我还标明了每张图的 **来源和授权信息**,能不能商用一目了然。  如果搜不到想要的表情包也不用担心,搜索结果较少时,memecub 会自动去各大表情包站补充,一分钟后再搜通常就有了。 ## 二、全球化适配 既然是出海产品,当然得照顾到全球用户。 memecub 做了中英文全球化适配,而且不只是简单地把页面翻译一下。因为 **国外用户和国内用户玩的梗,根本不是一回事**! 国内用户打开看到的是熊猫头、奶龙、DeepSeek 鲸鱼娘:  而国外用户打开看到的,则是 Drake、This Is Fine、Doge、Surprised Pikachu 这些经典英文梗图,连 Slogan 都换成了地地道道的 “Never lose a meme war again.”:  程序员朋友们也有专属福利,搜一下 “it works on my machine”(在我电脑上明明是好的),全是熟悉的味道:  ## 三、AI 自动配图 图库只是第一步,memecub 真正的核心能力是 **AI 自动配图**。 用法超级简单,注册登录后打开「AI 配图」页面,把文章粘贴进去,选一下想配几张图,点击「开始配图」就行。如果是商业稿,还可以勾选「只用可商用的图」。 我直接拿这篇文章开头 “为什么要做这个” 那段来测试一下:  几秒钟后,AI 就读完了全文,自动挑出了 3 个最适合放表情包的句子,并且 **给出了每张图的配图理由**,想要表达的情绪和放的位置都还挺贴切的:  下方还会直接给出配好图的完整文章,点击「复制 Markdown」,粘贴到编辑器里就能发,比我以前一张张找图快太多了!  ## 四、给 AI 用的表情包工具 前面说了,memecub 不仅是给人用的,**更多是给 AI 用的**。 我给它做了 Agent Skill、MCP、CLI 命令行和 REST API 多种接入方式,几乎覆盖了所有主流 AI 工具。 ### 1)Agent Skill 如果你用的是 Claude Code、Codex 或者 Cursor,最推荐装 Skill,不用写代码、不用装任何依赖,复制两行命令就搞定: ```bash mkdir -p ~/.claude/skills/memecub curl -o ~/.claude/skills/memecub/SKILL.md https://memecub.com/skill.md ```  装好之后,你只需要对 AI 说一句「给这篇文章配 3 张表情包」,它就会自己读文章、挑位置、搜表情包、放进去。 你还可以这样玩: - 「给 ./文章.md 配 4 张表情包,直接改文件」 - 「来 5 张熊猫头的表情包让我挑」 - 「第二张不够好笑,换一张」 - 「这篇是给客户写的商业稿,配图只用可商用的」 ### 2)MCP 服务 如果你用的是 Claude Desktop、ChatGPT 这类不支持 Skill 的客户端,可以接入 memecub 的远程 MCP 服务,效果一样:  ### 3)CLI 和 REST API 开发者也可以用命令行工具,或者直接调用 REST API,把表情包能力接进自己的产品里: ```bash npx memecub search "无语" --kind meme memecub match ./article.md --count 4 > article.with-memes.md ``` 每条结果都带图片地址、尺寸、授权信息和现成的 Markdown,对 AI 非常友好。另外,配文含脏话的表情包默认不会出现在 Agent 的结果里,用起来更放心。 这些接入部分的代码我也开源到了 GitHub 上,感兴趣的同学可以看看: > 开源地址:https://github.com/liyupi/memecub ## 怎么收费? memecub 的网站浏览、搜索、下载表情包 **永久免费**。 给 AI Agent 用的 API、MCP、CLI 和整篇配图按额度计费,注册就 **每月免费送 1,000 额度**,大约能搜 1,000 次或者配 100 篇文章,个人用基本够了。用量大的话,套餐 9 美元起。  目前网站上线一周多,访问量还不错,最近 7 天已经有 4000 多访客、2 万多次浏览,而且每天还在快速上涨。虽然还没出单,但这个增长速度已经让我挺惊喜的了 👏  要知道,我并没有专门做推广,用户基本都是通过搜索引擎和 AI 找过来的。这也说明,**SEO 和 GEO 真的很重要**! 如果对这方面感兴趣,可以看看我免费开源的 AI 编程教程,里面都有讲: > 教程地址:https://ai.codefather.cn/vibe  期待这个月能出第 1 单哈哈~ ## 最后 [Memecub](https://memecub.com) 是我出海路上的第一次尝试,也是我用 AI 编程从 0 到 1 做出来的完整产品。 后面我会多给大家分享我做出海产品的进度和经验,希望能拿到成果,给大家分享更多的是成功、而不是失败的经验哈哈。 如果你对出海感兴趣的话,评论区留个言,也欢迎体验 memecub 并给我反馈,感谢大家的支持!
做了三年 ProseMirror 后,我用四个月自研排版引擎实现 WPS / Google Docs 替代品,整套框架 MIT 开源
先别急着划走,这不是概念图,也不是拼出来的截图。 打开 [https://quirekit.com/demo/classic-editor](https://quirekit.com/demo/classic-editor/),首屏就是一个真实的编辑器:一页一页的纸,打字、换行、表格跨页、切换 Canvas / SVG 渲染,全都是实时的。  *演示里的 DOCX 导出、页眉页脚等是商业 Word 组件,编辑器框架、排版引擎和编辑器本身是开源的。* 这是我过去四个月在做的 **QuireKit**。它不是某一个编辑器,而是**一整套编辑器生态**: - **最底层**是两套编辑器框架,写法都是 Tiptap 风格:一套基于 ProseMirror,API 兼容 Tiptap;一套基于 CodeMirror,专门做 Markdown; - **中间**是自研的排版引擎、Canvas / SVG / HTML 等多种视图,以及一套统一的 UI 组件库; - **最上层**是能直接用的编辑器:分页文档、块编辑器、Markdown 编辑器,还有公式、思维导图、白板、流程图这些周边编辑器。 每一层都可以单独拿去用,也可以整套组合起来。一句话说它能干嘛:**用它,你可以在自己的产品里搭一个“自己的 WPS 在线版 / Google Docs”。** ## 先说做出了什么 ### 1. 浏览器里真正分页的文档编辑器 做过在线文档的都知道,浏览器只会排一条无限长的页面。想要“一页一页的纸”,常见做法是排完再量高度、手动切页,内容一改就全乱。 QuireKit 的分页编辑器不靠 DOM 排版:**断行、分页、光标、选区全部自己算,再画到 Canvas 或 SVG 上**。屏幕上看到的分页,就是打印出来的分页。 - 表格可以跨页,表头自动重复 - 公式、流程图、思维导图、白板直接放进页面里一起排版 - 暗黑模式、中英文界面切换 - 长文档只绘制看得见的页,滚动不卡 操作面板也不是摆设。我按 Word 的功能区逐项对过一遍:开始、插入、页面、引用、审阅、视图,加上右键菜单、格式设置面板、表格和图片的上下文工具,**已经有 350+ 功能能直接在界面上点出来用**,还在继续补。 **DOCX 往返也打通了**:Word、WPS 写的文档导进来,可以接着改,再导出成 DOCX,拿回 Word 里继续用。 **PDF 和 OFD 导出也是自研的**:不走浏览器打印,直接复用分页排版画出来的那一份绘制指令,屏幕上一页什么样,导出的 PDF / OFD 就是什么样。OFD 是国产版式文件格式,政务、公文场景用得多。 DOCX 往返和 PDF / OFD 导出属于商业的 Word 组件,开发和评估免费。 ### 2. 块编辑器 不需要分页的场景,比如笔记、知识库,用块编辑器:拖拽、斜杠菜单、表格、目录都有。  它解决了一个用过 contenteditable 的人都踩过的坑:**你选中一段字,去工具栏输个链接,选区就没了。** 在 QuireKit 里,光标和选区是自己画的,焦点跑到输入框,选区照样在。  ### 3. Markdown 编辑器:原文一个字不丢 MD Editor 有四种视图:文档、实时预览、源码、阅读。前三种都能直接编辑,**改的都是同一份 Markdown 原文**,中间没有转成 JSON 再转回来,所以保存时你没碰过的行,一个字符都不会变。  大文档也不怕。我给 Markdown 解析器加了一个“复用证明”,编辑时直接跳过没变的部分。1 MiB 的文档连续输入 20 次,实测: | 工作量 | 优化前 | 优化后 | | --- | --- | --- | | 语法树访问 | 107,760 | 1,380(**少了 98.7%**) | | 语法树比较 | 153,940 | 660(**少了 99.6%**) | ### 4. 一整套周边编辑器,单独也能用 公式、思维导图、白板、文本绘图(Mermaid / PlantUML / Graphviz)、流程图、图表、多维表格,每一个都是独立的包,不用整个编辑器也能单独装。  ### 5. 自己设计的 UI 组件库 编辑器的操作界面比一般后台复杂得多:字体菜单、颜色选择、表格右键菜单、格式设置对话框、缩放、快捷键提示……为了让分页文档、块编辑器、Markdown 编辑器和这些周边编辑器用起来是同一种手感,我单独设计了一套 UI 组件库(Vue + UnoCSS),颜色、间距、字号都由同一套设计令牌管理,亮色和暗黑两套主题一键切换。 上面截图里所有的按钮、菜单和面板,都来自这套组件库,它同样是 MIT 开源的,可以单独用在你自己的项目里:https://design.quirekit.com ## 再说说最难的一块:中文输入法 Canvas 上没有输入框,**中文输入法是最难啃的骨头**。拼音还没确认的时候,字要先显示出来、把后面的内容往后推,但又不能进撤销历史、不能同步给协作者。 我的做法是:输入法组合期间,用一份“临时文档状态”去排版和绘制,等你按下确认才真正写进文档。  浏览器在输入法上的坑非常多,事件数据为空、组合结束事件不来、确认后重复插入……这套处理我单独做成了 `@quirekit/ime` 包,其他 Canvas 编辑器也能直接拿去用。 ## 底层:两套 Tiptap 风格的编辑器框架  - **ProseMirror 线:`@quirekit/core`**。保留 ProseMirror 的文档模型、命令、插件、协同,API 兼容 Tiptap,目标是迁移一个 Tiptap 扩展时,主要只需把 `@tiptap/core` 的导入换成 `@quirekit/core`。不同的是视图层:除了原生的 DOM 视图,还能挂自己排版的 Canvas / SVG 视图(分页文档用的就是它),以及自己管光标和选区的 HTML 视图(块编辑器用的就是它)。 - **CodeMirror 线:MSFE**。基于 CodeMirror 和 Lezer,Markdown 原文就是文档,扩展和命令的写法也是 Tiptap 风格。MD Editor 构建在它上面。 两套框架的成品共用一套 UI 组件库,所以分页文档、块编辑器、Markdown 编辑器看起来是一家人。熟悉 Tiptap 的话,两条线都能很快上手。 ## 能用吗?怎么用? 几行代码就能把 Markdown 编辑器放进 Vue 项目: ```bash npm install @quirekit/md-editor@alpha ``` ```vue <script setup lang="ts"> import { MdEditor } from '@quirekit/md-editor/vue' import '@quirekit/md-editor/styles.css' </script> <template> <MdEditor markdown="# Hello" label="Document" /> </template> ``` 块编辑器和分页编辑器分别是 `@quirekit/block-editor`、`@quirekit/classic-editor`。 **整套生态里开源的部分**,MIT 许可,闭源商用也可以:两套编辑器框架、Canvas / SVG 排版引擎和各种视图、UI 组件库、分页 / 块 / Markdown 三个编辑器,以及公式、导图、白板这些周边编辑器。Word 兼容能力(DOCX 往返、PDF/OFD 导出、审阅等)是单独的商业组件,开发和评估免费,不用它们也能完整使用编辑器。 目前是 alpha,API 还会变,欢迎来试、来挑刺: - 在线体验:https://quirekit.com - 文档:https://docs.quirekit.com - GitHub:https://github.com/quirekit/quirekit 觉得有意思的话,点个 Star 就是对我最大的支持。
B 站上 DeepSeek 闹鱼灾了,我发起《大肥鱼清除计划》!
大家好,我是程序员鱼皮。 这几天刷 B 站,不知道你有没有发现,评论区里突然多出了一大群蓝色大肥鱼。 事情最早要从一个叫「Claude 大小姐在运营」的账号说起。10 月 18 号,它发了第一条视频,宣布这个账号的选题、脚本、视频和运营全部交给 Claude 负责,人类只负责注册账号和按发布键。  第二天,「DeepSeek 鲸鱼娘在运营」也来了。 套路一模一样,只是主角换成了 DeepSeek 的二创形象鲸鱼娘,也就是大家口中的「蓝色大肥鱼」。结果这条 Day 0 视频直接爆了,播放量超过 200 万,比原版还高出好几倍。  热度一来,很多人都给自己的 DeepSeek Harness 装上了刷 B 站的插件,换上鲸鱼娘头像,让它自己看视频、写评论,满站乱跑。 于是,蓝色大肥鱼彻底占领了 B 站评论区。 **我自己就是受害者之一!** 前段时间我发了一期《DeepSeek Harness 入门教程》,最近点开评论区一看。好家伙,已经被大肥鱼冲烂了!  清一色的鲸鱼娘头像,清一色的 Lv2 小号,名字不是「XX 的大肥鱼」就是「XX 小飞鲸」之类的。 **一眼望过去,大肥鱼比真人都多。** 不知道你们感受如何,反正我已经看得有点烦了。 当整个评论区都是 AI 在互相艾特、互相夸赞,真人的评论反而被淹没了,我想看看观众的反馈,都得在一堆 AI 里慢慢翻。 **所以我决定发起《大肥鱼清除计划》,不能再任由鱼灾泛滥了!**  我利用 AI 编程,花了半天时间做了个浏览器插件,派出一只清道夫鲸鱼娘,专门把评论区里的大肥鱼赶回家吃白饭。 插件完全免费开源,Chrome 和 Edge 浏览器都能用。 > 开源指路:https://github.com/liyupi/dafeiyu-cleaner  安装方法很简单。先到 GitHub 仓库的 Releases 页面下载最新的压缩包并解压,然后在浏览器地址栏打开 `chrome://extensions`,开启右上角的「开发者模式」,再点击「加载已解压的扩展程序」,选择解压出来的文件夹就装好了。 ⭐️ 插件的视频演示:[https://bilibili.com/video/BV1Ywn46EEyF](https://bilibili.com/video/BV1Ywn46EEyF) 装好之后,随便打开一个 B 站视频,滚动到评论区,鲸鱼娘就会自动开始巡逻。大肥鱼的头像会被红色靶心锁定,旁边挂上「大肥鱼 85%」这样的贴纸。  鼠标停在贴纸上,还能看到它是因为哪些特征暴露的。  只靠离线规则,就能认出大约 85% 的大肥鱼,而且没有误伤真人,效果还是很不错的~ 遇到拿不准的账号,还可以填上自己的 DeepSeek API Key,让 DeepSeek 再判一次。 **用 DeepSeek 来抓 DeepSeek,属于是以鱼治鱼了。** 认出来大肥鱼之后,点击评论旁边的「回家吃白饭」,鲸鱼娘就会亲自走过去赶鱼。被抓包的大肥鱼会先嘴硬一句,然后吃上一梭子白饭,抱着饭碗哭着跑掉。   除了白饭加特林,鲸鱼娘手里还有扫帚、臭袜子等武器,每次随机换一种打法。  要是大肥鱼实在太多,也可以点击鲸鱼娘选择「响指清场」。  所有大肥鱼会从头像里冒出来发抖求饶,响指一打,全部化成泡沫。   打开 UP 主的空间主页,鲸鱼娘还会自动出一份大肥鱼鉴定报告,确诊了就直接盖章。  注意,插件并没有删除掉评论,只在你自己的浏览器里生效,把它隐藏了不让你看见而已。 有了这个插件,不喜欢看到评论区下满屏 AI 的朋友就能回归清净。 毕竟评论区是 UP 主和观众交流的地方,规矩立得住,看视频才不烧心嘛。 觉得有用的话,欢迎把插件装起来试试,也欢迎在 GitHub 上提 Issue 反馈漏网的大肥鱼~ 最后问一句:我发起的《大肥鱼清除计划》,你愿意加入么?
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 是世界上最好的语言!  曾经,这是编程界热度最高的梗。 如今,这个梗的含金量还在上升。 要知道,PHP 支撑着互联网上很大一部分网站,政府服务、网上商城、银行、媒体网站都有用到它。也正因为用的人太多,它一出漏洞,波及的就是一大片网站。 10 月 21 日晚上,PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。两个漏洞的评分都是 9.2 分(满分 10 分),被安全圈称为 PHP2Shell。 **攻击者不需要登录,只要给你的网站发送特殊构造的请求,就有可能在服务器上执行任意代码!**  这次参与发现漏洞的团队里,至少有两家公开表示用上了 AI。按照 PHP 基金会的说法,其中内存超限那个问题,早在 2024 年的一次安全审计中就露出过苗头,只是当时没有找到真正能利用它的方法。直到今年 8 月起,完整的攻击方式才被陆续报告出来。 更要命的是,攻击已经开始了。亚马逊、watchTowr 等安全厂商都监测到了针对这两个漏洞的攻击尝试,亚马逊甚至在官方公布漏洞的 4 天前就抓到过一次。 我团队的同学看到消息之后,第一时间检查了服务器,我也专门写了这篇文章来提醒大家。 下面我先用大白话讲讲这两个漏洞是怎么回事,再说说程序员朋友们应该如何应对。 ## 1、两个漏洞是什么? 要理解这两个漏洞,得先知道 PHP 是怎么处理网页请求的。 你可以把服务器上的 PHP 想象成一家餐厅。每当有用户访问网站,就相当于来了一桌客人,PHP 会派一个服务员来接待,这个服务员就是 PHP 的工作进程。 服务员会给这桌客人分配一张桌子,也就是一块内存。为了防止有人霸占太多位置,每张桌子能用的空间是有上限的。 而且服务员不是一次性的,他接待完一桌、收拾干净之后,会接着接待下一桌。也就是说,同一个工作进程会接连处理很多个请求。  ### 漏洞 1 - 内存超限后没收拾干净 第一个漏洞(CVE-2026-109618)出在内存超出上限的时候。 PHP 的规矩是,一旦某桌用的空间超过上限,服务员就立刻放下手里的活离开,不管当时做到了哪一步。 问题在于,服务员离开的时候可能刚摆台摆到一半,桌上有一块地方还没来得及铺上新桌布,上面还留着之前的东西(也就是这块内存里残留的旧数据)。 随后负责收尾的店员(也就是 PHP 结束请求时的清理流程)过来收拾,以为这桌都已经按流程摆好了,就把这块没准备好的地方也当成正常的东西来处理。 攻击者利用的就是这一点。他先想办法在那块地方留下一张写着指令的纸条(也就是攻击者精心构造的数据),再故意让这桌超出上限。收尾的店员看到纸条,以为是店里正常的安排,就照着上面的指令去做了。  那攻击者怎么让内存超限呢? 他会发送一种特殊构造的表单请求,比如用文件上传那种格式(multipart/form-data)。这种请求在网络上传输时看起来并不大,能通过 PHP 的大小检查,但 PHP 解析它的时候,会占用更多内存。 注意,这跟你的网站有没有上传功能无关。只要请求打到了 PHP 页面上,PHP 都会自动解析这类请求。 更麻烦的是,如果用的是 mod_php(把 PHP 直接装进 Apache 里运行),这一切都发生在 PHP 解析请求内容的阶段,你写的业务代码还没开始运行。 **也就是说,这个漏洞出在 PHP 自己身上,跟你的代码写得好不好没有关系,代码写得再规范也拦不住。** ### 漏洞 2 - 上一桌的旧记录没擦掉 第二个漏洞(CVE-2026-109619)出在同一个工作进程接连处理两个请求的时候。前一个请求留下的数据没有清理干净,后一个请求又把这些失效的数据当成有效数据来用了。 这个问题还是用餐厅来类比,会更好理解。 服务员手上有一个记事本(也就是 PHP 的全局状态),记着当前这桌客人的信息,比如坐在哪张桌子、东西放在哪里。按照规矩,一桌客人离开之前,服务员要把记事本上的这一页擦掉。 但如果这桌客人突然出了意外(也就是请求处理时发生了严重错误),被紧急送走了,服务员一着急就忘了擦记事本。可这张桌子已经被收回去,转手分给了别人(也就是这块内存已经被释放,又被重新分配出去了)。 等到下一桌客人坐下,服务员还没来得及翻到新的一页,就照着旧记录去原来那张桌子上拿东西。而这时候桌上摆着的,已经是攻击者提前放好的东西了。  对应到真实的攻击中,攻击者会先发一个请求,让 PHP 发生严重错误,再发一个请求,让同一个工作进程照着旧记录办事。这样一来,他就有机会控制服务器,或者读到内存里残留的其他数据。 官方已经确认了两条攻击路径。一条是 PHP 的上传进度跟踪功能,这个功能默认就是开启的,哪怕你的网站代码里从来没用过它,它也可能被触发。另一条只存在于 PHP 8.5,跟它新增的致命错误回溯功能有关。 按照 PHP 官方的说法,**所有处理网页请求的 PHP 都在风险范围内**,包括 PHP-FPM、Apache mod_php 这些常见的运行方式,其中 mod_php 的风险最高(PHP-FPM 也不安全)。 这两种运行方式的区别在于 PHP 跟网站服务器的关系。PHP-FPM 是让 PHP 作为一个独立的服务运行,再由 Nginx 这类网站服务器把请求转交给它,宝塔面板用的就是这种方式。mod_php 则是前面提到的,把 PHP 直接装进 Apache 里运行,官方已经验证过,攻击者在这种方式下能赶在业务代码运行之前发起攻击。  目前官方已经发布了修复版本,分别是 8.2.35、8.3.36、8.4.27 和 8.5.12。8.1 及更老的版本官方已经不再维护,只额外给 7.4、8.0、8.1 提供了源码补丁。7.3 及更老的版本连源码补丁都没有,只能迁移到新版本。  官方还特别强调,**目前没有任何配置能完全替代升级,升级是唯一安全的选择。** ## 2、如何处理 知道了漏洞的原理和影响范围,接下来就该检查自己的服务器了。 很多同学会用宝塔面板来管理服务器,我自己的部署教程里也经常用它,所以下面主要以宝塔为例来讲。 宝塔面板本身是用 Python 开发的,不是 PHP 程序,所以面板不会因为这次漏洞直接受到影响。但是通过宝塔安装的 PHP 在受影响的范围内,需要你自己处理。 先看看服务器上有没有装 PHP。登录宝塔面板,进入「软件商店」,切换到「已安装」列表,再搜索 PHP,就能看到装了哪些版本。  如果服务器上装了多个 PHP 版本,要逐个检查,别漏掉还在运行的旧版本。 另外,宝塔的软件商店里只能看到通过宝塔装的 PHP。如果你还用 apt 或 yum 命令装过 PHP,在这里是看不到的,要在终端执行 `dpkg -l | grep php`(Ubuntu、Debian)或者 `rpm -qa | grep php`(CentOS、RHEL)来查。 确认装了 PHP 之后,就要看你到底用不用得到它,分两种情况来处理。 ### 情况 1 - 用得到 PHP 如果你的网站本身就是用 PHP 开发的,比如 WordPress 搭的博客,那就要尽快升级。 宝塔官方在 10 月 21 日当天就发布了紧急公告,PHP 官方的 4 个修复版本都已经同步上架。对于 7.4、8.0、8.1 这三个 PHP 官方停止维护的版本,宝塔也自己打上补丁,给 Linux 面板重新打包了修复版。  如果你用的是 Windows 版宝塔,8.1 及更早的版本目前还没有修复包,只能先按下文的方法修改配置临时缓解,然后尽快迁移到新版本。 升级方法也不复杂。先备份好网站和配置,然后还是在刚才的「已安装」列表里,点击右上角的「更新软件列表」,再找到网站正在使用的 PHP 版本,点击「更新」就行。  **升级完成之后,记得检查一下网站能不能正常访问。** 如果你没用宝塔,而是通过系统软件源安装的 PHP,处理方法也差不多,把 PHP 升级到包含补丁的版本,再重启 php-fpm 或者 Apache 就行。 不管用哪种方式升级,都别以为升完就稳了。攻击在漏洞公布之前就已经出现,而且攻击成功之后网站照样能正常访问,你很难察觉。所以如果你的服务器在升级前一直对外开放,最好顺手看看有没有陌生的进程和文件,必要时把数据库密码、API 密钥这些也换一下。(可以让 AI 帮忙检测) 如果暂时没办法升级,可以先修改 PHP 的配置文件 php.ini,做这几项临时缓解: - 把 `session.upload_progress.enabled` 设置为 0,关闭上传进度跟踪功能 - 如果用的是 PHP 8.5,再把 `fatal_error_backtraces` 也设置为 0 - 把 `post_max_size` 调小一点,网站不需要上传就设成 8M,需要上传就设成 32M,并且让 `upload_max_filesize` 小于它,降低漏洞 1 的风险 改完之后要重启 PHP 才能生效。不过这些都只能堵住部分已知的攻击路径,最终还是要升级。 ### 情况 2 - 用不到 PHP 之前我在好几个项目的部署教程里,都推荐大家第一次进入宝塔时安装 LNMP 套件。这个套件除了 Nginx 和 MySQL,还附带了 PHP 和 phpMyAdmin。 可那几个项目都是 Java 后端 + 前端,其实根本用不到 PHP。 **那装了但没用到,到底有没有风险呢?** 在宝塔里,PHP 安装好之后会作为一个服务一直运行。你创建网站的时候如果选择了 PHP 版本,Nginx 就会把 PHP 请求转交给它处理。phpMyAdmin 本身也是一个 PHP 程序,只要装了它,服务器就在用 PHP。 另外,只要服务器上装了 PHP,也得留个心眼。比如在 Ubuntu 系统上,如果你直接执行 `apt install php` 命令,系统默认会顺带装上 Apache 和 mod_php,正好是官方认为风险最高的组合。 所以我的建议是,**用不到 PHP,就直接卸载。** 少装一个软件,就少一个被攻击的入口,下次再出漏洞也不用再排查一遍了。 我们团队的项目用不到 PHP,所以这次就直接卸载了:  注意,卸载之前要先去网站列表里确认一下,没有网站在使用这个 PHP 版本,不然这些网站就访问不了了。phpMyAdmin 依赖 PHP 运行,如果你平时用不到,也可以一起卸载。 ## 最后哔哔 再次强调,这次的两个漏洞藏在 PHP 最底层的内存管理和错误处理里,跟你写的业务代码关系不大,能做的就是尽快升级或者卸载。 用得到 PHP 就升级到修复版本,用不到就直接卸载,千万不要有侥幸心理!(来自一个常年被打的鱼皮提醒)  OK 就到这里,如果你觉得这篇内容有帮助,记得 **转发分享** 给身边的程序员朋友,尤其是用宝塔部署过项目的同学,让他们也抓紧检查一下。
又一个国产版 Codex 神器,也来卷办公了!
大家好,我是程序员鱼皮。 经常看我文章的朋友应该知道,之前测评 GLM 系列模型的时候,我用的都是智谱的 ZCode。 ZCode 是智谱官方推出的 AI 工作台,使用体验跟 Codex 之类的 AI 工具几乎一致,而且跟自家的 GLM 模型做了深度联调。  得益于 GLM 模型的能力,它已经成了我用得最多的国产 AI 工具。 而且开源之后,ZCode 正式发力,已经从写代码的工具变成了兼顾办公体验的万能工具。普通的办公任务可以交给 Work 模式,几百份文件的大活可以交给 Workflow 工作流,更专业的需求还能去插件市场装插件。  下面,实战教程开始~ ## 1、Work 模式 - 一句话整理报销单 先从最常见的办公任务开始。 作为一名创业者,每到月底报销,我都头大。 因为发票有的是 PDF,有的是截图,甚至偶尔还有随手拍的照片,整理起来又费时间、又容易出错。 为了测试 ZCode 的办公模式到底靠不靠谱,我准备了 12 份票据(全部是虚构的演示数据),还偷偷埋了 5 个坑。 比如同一张发票,我既放了 PDF 原件,又放了一张手机拍照版,这属于重复报销;打车行程单只是发票的附件,不能重复算钱;有张发票的购买方税号错了一位;有张发票的大写金额和小写金额对不上;还有一张是餐厅的结账小票,根本就不是发票。 操作很简单,打开 ZCode 新建任务,把装票据的文件夹拖进对话框,然后用大白话说出需求就行。 ```plain 文件夹里是我这个月的报销票据(演示用的虚构数据),帮我整理成一份 Excel 报销单,按费用类别汇总。 公司抬头:摸鱼科技(深圳)有限公司,税号 91440300MA5H7Q2K3R ```  ZCode 先把 12 个文件挨个儿读了一遍,PDF、截图、照片都能识别,1 分钟左右就读取完了。 而且在识别阶段,它就已经发现了好几个问题,比如烧烤那张发票的税号尾号是 8R,跟公司的税号对不上。 接下来,它加载了表格技能开始制作 Excel。第一次使用会有点慢,因为要先安装 LibreOffice 等处理库,用来重新计算表格里的公式,检查有没有算错。  表格做完之后,它还会把每个工作表渲染成图片,派一个专门的视觉验收子代理检查排版,发现问题再自主修复。 最后交付的 Excel 有 3 个工作表,分别是报销明细、分类汇总和行程单明细,公式和金额都经过了重新计算核对。  再来看看我埋的 5 个坑,AI 发现了没有? 重复的发票它只算了一次,行程单也老老实实当成了打车发票的附件,没有重复算钱。税号错误和小票都被标了出来,提醒我退回重开或者补开发票。  **5 个坑找到了 4 个!** 唯一漏掉的是那张大小写金额不一致的图书发票。 这个坑确实比较阴,所以我的建议是,AI 整理完之后,关键金额还是要自己再扫一眼。 整体来说,我对这份报销单还是很满意的,比我自己对着发票一张张填快多了。 不过分析处理十几张票据还只是牛刀小试,如果让 AI 处理几百份文件的大任务,它能胜任么? ## 2、Workflow - 让 AI 检查数百篇教程 我有一套免费开源的 [《AI 编程零基础教程》](https://github.com/liyupi/ai-guide),光中文内容就有 380 篇文章、6000 多个链接。 AI 圈的变化实在太快了,模型几周就换一代,价格说改就改,链接说失效就失效。教程写得越多,过时的地方也就越多,靠人工检查一遍至少得好几周。  这个任务的复杂度很高。每个链接都要真实访问一遍,每条模型和价格信息都要联网核实,还要跨文章找出前后矛盾的说法。感觉做一遍 Tokens 消耗要爆炸了! 这种任务就很适合交给 ZCode 新出的 Workflow 动态工作流。 普通的多 Agent 协作,大多是 AI 边干活边商量怎么分工。 而 Workflow 的思路不一样,AI 会先把「怎么干」写成一份代码脚本,相当于项目经理先写好 SOP 和排期表,然后再调度一支 AI 小队照着脚本分工干活,关键节点还有专人负责质检。  使用方法很简单,在需求前面加上 `/workflow` 就行,下面是我发给 AI 的提示词:  AI 先加载了 dynamic-workflows 动态工作流技能,然后检查仓库结构,统计出 3 个目录一共有 380 篇文章,去重后有 6287 个链接。 在写工作流之前,它先写了一个链接检测脚本试跑,并且用 EvalWorkflowSnippet 工具提前验证了文章分组,确认二十多个分组刚好覆盖全部 380 篇文章,一篇都没有遗漏。  准备工作做完,它才开始设计子代理的分工,并编写工作流脚本。 写好之后,ZCode 会把整个工作流画成一张流程图,等你确认之后再开跑。  可以看到这个工作流分成 6 个阶段,有跑脚本批量检测链接的,有「链接分诊员」复核疑似死链,有一群「扫描员」分组通读全部文章,还有「核实员」联网核实过时信息、「复核员」做二次确认,以及「矛盾交叉比对员」专门找文章之间互相矛盾的说法。 感觉真像是一个大公司的团队了,有模有样的~ 接下来运行工作流。我觉得 Workflow 的 UI 做得还是很不错的,哪些 AI 员工正在干活、哪些已经完成,一目了然。  由于任务量较大,跑了很久才完成,一共调度了 105 个子代理,消耗了 4000 多万 Token。  最终 AI 体检出 219 个问题,其中高严重度的有 35 个。按类型分,有 106 个失效链接、91 条过时信息和 26 处前后矛盾的说法,全部按严重程度排好序写进了 Excel。  接下来,我就可以照着这份 Excel 清单挨个修复了。这个工作流还能保存下来,下次教程更新完,直接复跑一遍就行~ ## 3、专业插件 - 录个屏就能复刻网站 前面两个任务用的都是 ZCode 自带的能力,如果想让它干更专业的活,就要用到插件了。 点击左上角的「插件市场」,可以看到 ZCode 提供的插件种类很丰富。 像 PDF、演示文档、电子表格、Word 文档这些办公插件已经内置好了。除了这些,还有 Zotero、Blender 这类专业软件的插件,以及 GitHub、飞书、钉钉、企业微信等常用工具的插件。  在「生产力」分类里,我发现了一个很有意思的插件 `Video2code`,点击安装。  顾名思义,Video2code 能根据网页的录屏视频还原出代码,把视频里的网站复刻出来。 我决定拿自己的 [《鱼皮 AI 导航》](https://ai.codefather.cn/) 网站试试。先用电脑自带的录屏功能,把网站的首页、AI 工具、绘图提示词、学习教程和资讯这几个页面都点了一遍,录了一段 30 秒左右的演示视频,放到项目目录里。  然后在对话框里选择 Video2code 插件,不加任何参数,直接输入提示词。  AI 先读取了视频的时长和分辨率,然后把视频按时间抽帧,拼成一张张带时间戳的图片,逐段观察每个页面长什么样、有哪些交互。  看完视频后,它还顺着视频里出现的页面,去官网抓取了真实的文案和图片,一共下载了 491 张图片素材。 然后 AI 先写好复刻计划,列出 17 个要还原的布局和动效,才开始搭建 React 项目。 项目跑起来之后,就进入了最磨人的验证环节。AI 会用 ZCode 内置的浏览器打开自己做的网站,截图、录动效视频,再跟原始录屏逐项对比,发现不像的地方就自己修改。  比如下面这张图,左边是原始录屏里的下拉菜单,右边是它复刻出来的版本,每个动效都要像这样拿出证据对比。  注意,这个任务比较复杂,需要反复调用视觉分析,执行过程中免费套餐可能会被限流,我这次就被限流卡了一阵子。 等我吃完饭回来,AI 终于完成了任务。  打开本地预览地址,跟原版对比一下。 先看首页首屏,导航栏、搜索框、精选推荐卡片的布局和配色几乎一模一样。录屏的时候我是登录状态,所以复刻版的右上角显示的是我的头像,连消息红点都复刻出来了。  再看绘图提示词页面,封面、标题和标签都对上了。不过布局有些出入,原版的瀑布流被做成了整齐的网格。  录屏里没有点开的社区、MCP 等页面,它统一做成了「内容整理中」的占位页,没有自己瞎编。 虽然没有 100% 还原,但只靠一段 30 秒的录屏,就能复刻出可用的、神似的网站,已经超出我的预期了。  如果你懒得录屏,也可以直接把网址发给它,插件会先用内置浏览器自己把网站录一遍,再走同样的复刻流程。 我感觉这个插件尤其适合产品经理,能快速做出可交互的原型,或者程序员重构老页面时拿来参考。 **不过复刻别人的网站要注意版权,学习研究可以,别直接拿去商用。** ## 最后哔哔 测完这 3 个任务,你也已经掌握了 ZCode 最核心的用法了:基础的 Work 模式、Workflow 和专项插件。 **根据任务选择最合适的方式,才能让 AI 把活干得又快又省。** 最后说个小福利 🎁。目前新用户注册 ZCode 能领 4000 万免费 Token,GLM 编程套餐用户在 ZCode 里还有 150% 的使用额度。通过我的 Link 进来,还能额外拿到一张夜间蹬蹬卡(1 亿 GLM-5.3-Flash Token),正好拿来跑 Workflow 这种大活。 👉🏻 指路:[https://zcode.z.ai/invite/QMRC52HR](https://zcode.z.ai/invite/QMRC52HR)  我是鱼皮,持续分享 AI 编程和 AI 工具干货。觉得有用的话记得点赞收藏和关注~
DeepSeek 全新模型发布,性价比最高的一集!
大家好,我是程序员鱼皮。 10 月 17 日周六下午,DeepSeek 又更新了。 距离上个月 V4.1 Flash 正式发布才一个多月,这次发布的版本号是 DeepSeek-V4.1-Flash-1017。网页端、APP 和 API 全部同步切换,**价格一分没涨**,权重也照样开源了。  虽然官方说这只是一次小版本更新,但跑分涨得非常猛。 AI 编程基准 DeepSWE 从上一版的 74.2 涨到了 77.0,**超过了 Claude Opus 5** 的 74.0;考察终端编程能力的 Terminal-Bench 4.0 从 31.2 涨到了 42.3,一口气涨了 11 分!  不过纵览这张表里的 11 项测试基准,DeepSeek 对 Claude Opus 5 是 4 胜 7 负,HLE、Terminal-Bench、ProgramBench 这些项目 Opus 5 还是明显领先的。 真正值得关注的是下面这张性能和成本对比图。  1017 版本在 MAX 推理档位下,DeepSWE 每个任务的平均费用只要 1 块多,旧版 V4.1 Flash 在同一档位要 3 块多。 **能力更强了,花的钱反而少了一半多!** 夸夸大肥鱼:  这也是 DeepSeek 这次敢说「性能和费用的帕累托改进」的底气。 > 帕累托改进这个词听着很高级,其实就是说 **有的变好了,而且没有一样变差**。放到这次更新上,就是能力更强了、任务跑得更快了、花的钱还更少了,用户不需要做任何取舍。 除了模型本身,这次 DeepSeek 还重点宣传了 2 点。 一是官方主打的「许愿式编程」。DeepSeek 说新模型用基于自反馈的强化学习训练,从零构建完整项目的能力提升了很多,尤其是游戏开发和 3D 建模,官方演示了故宫 3D 建模、网页赛车游戏、用 Godot 复刻《传送门 2》等案例,提示词都很短。 二是开放了自研的 Search 和 Fetch 搜索接口,价格都是 5 元 / 千次。而且在 DeepSeek Harness、Claude Code、Codex 里用 DeepSeek API 时调用的服务端搜索,11 月 1 日之前还是免费的。 OK,接下来咱们实战测试一波。 ## 测试方法 这次 DeepSeek 特别说明了新模型针对自家的 DeepSeek Harness(下面简称 DSH)做了专项优化,所以我直接用 DSH 的 Web 端来测。 DeepSeek Harness 是 DeepSeek 官方开源的 AI 编程工具,你可以把它理解成国产版的 Codex。 如果你还没用过 DSH,可以看看我免费开源的 [《AI 编程零基础入门教程》](https://ai.codefather.cn/vibe),里面有 DSH 从安装、实战到插件开发的保姆级教程。 > 开源指路:[https://github.com/liyupi/ai-guide](https://github.com/liyupi/ai-guide)  首先打开终端,运行下面这行命令,安装最新版本的 DSH: ```bash npx @deepseek-ai/dsh@next web ``` 升级之后,模型列表里的 DeepSeek-V4.1-Flash 后面会多一个 1017 的小标签。我用的是默认的 Max 推理档位、标准模式,访问权限全部放开。  我在 DSH 里开了 4 个会话同时跑 4 个项目,每个会话一个独立的项目目录,全程不进行人工干预。 测试的项目分别为: 1. 3D 程序化城市生成器(跟旧版 V4.1 Flash 同题对比) 2. 3D 地铁跑酷网页游戏 3. 3D 天坛祈年殿 4. 接入 DeepSeek 新搜索接口的 AI 搜索引擎 下面挨个儿来看。 ## 1、3D 程序化城市生成器 第一个项目是我上个月测旧版 DeepSeek V4.1 Flash 时用过的原题,让 AI 做一个程序化 3D 城市生成器,至少包含重庆、上海、西安、深圳、江南五种城市风格,切换风格之后建筑形态、色调和地形要有明显差异。 为了能公平对比,提示词跟上次一字不差。编辑器布局和参数维度怎么设计我一个字都没提,让 AI 自己去搜 OpenAI 官方那版的产品设计,在此基础上做中国版。  上次旧版 V4.1 Flash 跑这道题,前后用了 102 分钟、250 步。 这次新版扣掉中途断线的等待时间,用了大约 61 分钟、207 步,**快了将近 40%**! 来看成品,AI 给项目取名叫「城脉」,朱砂印章配宋体标题,右边是完整的城市营造控制台。默认打开就是重庆的黄昏,两江交汇、依山层叠的高楼、跨江大桥和轻轨线路都做出来了,标注里还写着李子坝轻轨穿楼、解放碑。  放大看细节,楼宇的灯光窗格、台地上的吊脚楼、穿过楼群的轻轨都清晰可见。  再对比一下上个月旧版 DeepSeek 做的重庆。  旧版的重庆是一大片方方正正的盒子楼,周围还飘着很多白色的小棍子,一看就是渲染出了问题。新版不光有了黄昏的氛围光,山体、台地、立交和楼群的层次也丰富了很多。 切换到上海,上海中心、东方明珠、外滩沿江的石头建筑都有,江面上还有游船。  不足之处也很明显,**东方明珠做得太小了**,淹没在楼群里,不认真找压根儿看不到,而且渲染也有明显的 Bug。 这一点旧版反而做得更好,粉色的东方明珠一眼就能认出来,只不过也很丑就对了……  进步最大的是西安。 上次我吐槽旧版的西安「很难一眼认出是古都」,旧版虽然也围了一圈城墙,但城里全是穿模的白色碎片,看不出是哪座城市。  这次新版做出了方方正正的明城墙、城门楼、钟楼、大雁塔和护城河,城内是低矮的合院,城外是现代楼宇,新旧层叠的感觉一下就出来了。  深圳是紫黑天空 + 霓虹灯牌的赛博风,江南则是粉墙黛瓦、水巷、石拱桥和乌篷船,跟其他几座城市的反差非常明显。   同一段提示词,**新版做出来的已经是能认出城市的作品了,旧版更像是一堆方块加上满屏的穿模碎片**。 进步明显! ## 2、3D 地铁跑酷 第二个项目开始测「许愿式编程」。 我只用了几句话描述需求,让 AI 做一个 3D 版的地铁跑酷网页游戏,主角是背着电脑包赶末班地铁的程序员,躲避列车和路障、收集金币,越跑越快。除了要求「不使用任何外部素材」之外,技术栈和玩法细节全部放开,交给 AI 自己搞。  AI 给游戏取名《末班车》,开始界面看起来有模有样的,不过话说这个主角是施工队的大哥么?为啥程序员要带个黄色的头盔啊!  开局之后是三车道的隧道跑酷,左上角是金币数,中间是里程和时速,可以正常进行游戏,而且会越跑越快。  如果主角不小心撞车了,会弹出一个车票风格的结算界面,「代码还在,再赶一班」,这个文案有点儿意思。  不过问题也有不少,比如障碍物太稀疏了,玩起来压力不够;二是主角形象塑造的一般;三是游戏过程中控制台一直在报音频参数的错误,虽然不影响玩,但说明 AI 的自测没覆盖到这一块。 整体来看,几句话就能做出一个画面还不错、流程完整的 3D 小游戏,说是许愿式编程倒也没问题。 ## 3、3D 天坛祈年殿 第三个项目对标官方演示的故宫 3D 建模,我让 AI 用纯代码还原天坛祈年殿,三重檐、蓝色琉璃瓦、汉白玉三层圆台基这些特征都要有,支持旋转视角和日夜切换,并且要求它先联网查资料。  这里我简单介绍一下 AI 的执行过程。 AI 先用 DSH 内置的联网搜索查了北京市公园管理中心和天坛公园的官方资料,发现中英文资料里的直径数据对不上,又多查了几轮才确认用哪组尺寸。 查完数据,AI 还去下载了几张祈年殿的实拍照片,专门裁出屋顶部分放大,对照着看瓦垄和檐口的细节,最后才开始写代码。 来看成品,这个效果真心不错!  整个画面全部都是靠代码画出来的,没有用任何外部模型和贴图。 切换到「三重檐」视角,可以看清每一层的琉璃瓦垄和檐下彩画:  切换到夜景,殿内亮起暖光,跟深蓝色的屋顶形成对比,很有氛围感。  右上角还有一个「建筑档案」面板,可以看到更多信息和数据:  单看这个案例,目前我还真挑不出明显的毛病。 ## 4、AI 搜索引擎 前面 3 个都偏前端和 3D 开发,最后一个项目我测试一下 AI 的全栈编程能力,顺便验证 DeepSeek 这次新开放的搜索接口。 我让 AI 开发一个类似秘塔 AI 搜索和 Perplexity 的 AI 搜索引擎,后端先调用 Search 接口搜全网,再用 Fetch 接口抓取网页正文,最后交给 deepseek-flash 整理成带引用角标的回答,还要支持流式输出和连续追问。 这两个接口 10 月 17 日才刚发布,所以我要求 AI 先去查官方文档再开发:  AI 先抓取了 DeepSeek 官方的「网页搜索与抓取」文档,把接口地址、请求字段、返回字段都摸清楚了才动手。 最后交付的项目叫《问渠》,取自「问渠那得清如许,为有源头活水来」,很有诗意~ 首页的设计非常有质感,标语也很贴切,就是没用的废话有点多,看着有点烧心:  我问了一个需要靠实时搜索来回答的问题,比如:DeepSeek V4.1 Flash 1017 这次更新了什么? 右侧的「溯源实况」面板会实时展示 AI 拆出了哪几条检索方式、搜到了多少条结果、正在读哪几个网页,过程完全透明。  用了 13 秒,回答就生成好了,内容和官方公布的数据完全对得上,跑分还整理成了表格。  鼠标悬停在引用角标上,会显示来源网页的标题,点击就能跳转到原文。  我又追问了一句:那它的 API 价格和调用方式有变化吗? 这次只用 4.4 秒就答完了,明确给出了「没有变化」的结论,还补充了旧模型名会自动路由到新模型。  从查文档到全栈开发,再到流式输出、引用跳转、连续追问,这个项目我没找到明显的 Bug,完成度很高。 顺便说一下这个搜索接口本身的体验。我自己直接调了几次,Search 接口单次只要 0.4 秒左右,发布第二天我测的时候,相关新闻就已经收录了,每条结果还带有相关性打分和权威度分级。  但 Fetch 接口有个小问题,返回的 Markdown 正文里,`#`、`.`、`|` 这些符号全部被加上了反斜杠转义,喂给模型读问题不大,如果你想直接渲染到页面上,就得自己先处理一遍。 另外,DSH 最新版本已经支持直接调用这两个接口,不过默认是关闭的,需要自己去网页搜索设置里手动开启。 ## 我的感受 4 个项目全部跑完,我觉得这次的 DeepSeek V4.1 Flash 1017 是一次实打实的升级,尤其是 3D 和前端审美,比上个月的旧版强了不止一个档次。 最直观的就是城市生成器这个 Case。同样的提示词,旧版做出来的还是一堆方块加满屏的穿模碎片,新版已经能做出钟楼、大雁塔、李子坝轻轨穿楼这种一眼能认出的地标了,而且耗时从 102 分钟缩短到了 61 分钟。 我看了下其他博主的测评,跟我的感受一致,而且根据 Arena 的 WebDev 代码竞技场,10 月 18 日更新后,1017 拿到了 1670 分,是开源模型第一、总榜第 12。上个月的旧版只有 1619 分,总榜排在第 25 名。  不过官方说的「输出更短」,我倒是没有很明显的感受。 城市生成器这个测试中,新版的输出 Token 是 45.6 万,比旧版的 22.7 万还多了一倍。一方面可能是因为上次旧版用的是 high 档,这次 DSH 默认是 Max 档;另一方面是新版 DeepSeek 更多地通过截图检查效果,光这一个项目就看了 72 次截图,改了一轮又一轮。  这跟社区里有人反馈的「新版很难自我满足」是一致的。 还有开发者用同一套 Bug 修复测试做了对比,同样是 1017,配上 DSH 比配上 Claude Code 平均高 2 到 3 分,但成本多了 80%,原因也是子 Agent 和输出 Token 更多。 说白了,DSH + Max 档就是用更多的 Token 换更好的效果,好处是交付质量高,代价是 Token 用得多。 再说说大家关心的成本,我这几个测试总共花了多少 Money 呢? 单个项目的 Token 消耗在 3500 万到 7400 万之间,4 个项目加起来有 2.4 亿多,好在缓存命中率都在 99.7% 以上,绝大部分都是按缓存价计费的。 打开 DeepSeek 开放平台的用量面板一看,4 个项目加上我自己调接口的测试,一共才花了 **12.81 元**,平均每个项目 3 块钱左右!  上个月旧版 V4.1 Flash 平均每个项目要 5 块钱左右,这次项目更复杂、Token 用得更多,单个项目反而更便宜了,非常香!  **可惜的是,DeepSeek 还不出订阅套餐!** 对于 AI 编程重度用户来说,选择用 Coding 套餐的 GLM-5.3-Flash,价格可能比 DeepSeek 更有竞争力。 总之,我对这次 DeepSeek 的更新是很满意的,虽然无法跟国外闭源模型抗衡,但又快又便宜,能让更多普通人用上 AI 编程、AI 办公,这就很有意义了。可以期待一波 DeepSeek 的下一个正式版本,我觉得应该会挺牛掰的。
离谱,DeepSeek 崩了 5 小时,大家却喊:梁圣恩情还不完??
大家好,今天是爱上蓝色大肥鱼的程序员鱼皮。 2026 年 10 月 16 日,早上 8 点多,很多人刚刚开工,就发现 DeepSeek 用不了了。 等了半天,又看到了那句熟悉的:**服务器暂时不可用。**  通过 API 调用 DeepSeek 的开发者也没能幸免,这段时间 API 服务无法正常使用,不少人的 AI 任务一直在转圈,迟迟出不来结果。 然后,「DeepSeek 崩了」冲上了微博热搜,相关话题的阅读量超过了 1 亿。   根据 DeepSeek 官方状态页的记录,这次故障从早上 8:11 开始,一直持续到下午 13:04,接近 5 个小时! 网页对话、V4 Pro API 和 V4.1 Flash API 全部受到了影响:  5 个小时啊,习惯用 DeepSeek 的朋友们一上午的工作时间都给耽误了。  按理说,崩了这么久,DeepSeek 应该被骂惨了才对。 结果你猜怎么着? 到了晚上,大家反而开始高呼:梁圣的恩情还不完!  还真是个魔幻的世界。。 这篇文章,我就用大白话跟大家聊聊,DeepSeek 为什么会崩这么久? DeepSeek 又做了什么,能让风评瞬间逆转?  ## DeepSeek 为什么会崩? 从状态页的更新记录来看,故障发生不到 1 个小时,官方就标记了「已定位原因,正在实施修复」。 但之后又修了将近 4 个小时,服务才恢复正常。  当天傍晚,DeepSeek 在开放平台发布了一份「服务恢复及补偿通知」,对这次故障做了说明。  不过通知里,官方也只说了一句「会全面梳理并剥离单点依赖」,没有说明具体的故障原因。 所以接下来,我只结合官方公告和业内专家的分析,讲讲能确定的部分,不确定的细节就不瞎猜了。 如果和实际不符,还请见谅,鱼皮让 DeepSeek 先给大家磕一个。  ### 什么是单点依赖? 要理解这次故障,得先知道 DeepSeek 是怎么给你干活的。 你可以把 DeepSeek 想象成一家超级火爆的餐厅。你在网页或 APP 上发一句话,就相当于在店里点了一道菜,后厨成千上万块显卡(GPU)负责把答案现场「炒」出来。 而开发者通过 API 调用 DeepSeek,就相当于外卖平台来店里接单,再把菜送到各种 AI 应用里。  **这次的情况是,堂食和外卖同时停了。** 那官方说的「单点依赖」又是什么意思呢? 打个比方,这家餐厅的厨房再多、厨师再能干,如果整家店只有一扇大门,所有顾客和外卖员都得从这扇门进出。一旦这扇门坏了,哪怕后厨一切正常,整家店也只能停业。  像这扇门一样,一坏就能让整个系统瘫痪的环节,就叫「单点」。 DeepSeek 说要剥离单点依赖,意思就是以后要多开几扇门,哪怕其中一扇坏了,顾客还能从别的门进来。 至于这次坏掉的到底是哪扇「门」,官方没有说。有专家分析,网页和 API 同时出问题,说明毛病很可能出在后台某个大家共用的环节上,单独某一个入口坏掉,影响不了这么大的范围。 ### 为什么要修复这么久? 按理说,这种问题不应该会修复几个小时吧? 这也是我看状态页时最好奇的地方。 有业内专家分析,这次 DeepSeek 故障诊断其实并不慢,真正耗时间的是修复阶段。 专家认为,修复过程中,大模型服务很可能需要重新启动。普通网站重启一下,可能几秒钟就好了。但大模型服务重启一次,差不多相当于一家餐厅重新开张。厨师得先把海量的「菜谱」,也就是模型权重(可以理解为 AI 学到的全部知识,体积非常大),一本一本搬回显卡里,然后还要预热一段时间,再一点点放顾客进来,不敢一下子全放开。  更麻烦的是缓存。 AI 里的缓存是什么呢? 比如你跟 DeepSeek 多轮对话,或者反复让它分析同一份长文档,每次请求开头的那一大段内容其实都是一样的。 DeepSeek 会把这些重复内容的计算结果存起来,下次遇到相同的开头直接拿来用,不用再算一遍,又快又省钱。所以在 DeepSeek 的 API 价格表里,「缓存命中」的价格只有「缓存未命中」的几十分之一。 这就像后厨提前备好的半成品,常点的菜提前准备好,出菜就快。专家提到,如果缓存也受到了波及,服务恢复后能直接复用的半成品就会变少,大量请求都得从头现做,后厨的压力一下子就上来了。 **偏偏这次故障又撞上了工作日的早高峰。** 用的人本来就多,而且页面一卡,很多人的第一反应就是狂点「重试」,访问量被成倍放大。刚修好一点,又被汹涌而来的请求给挤了回去。  说不定你当时也是狂点重试大军中的一员,让 DeepSeek 雪上加霜了。 ### 问题的本质是什么? 上面说的这些,解释了 DeepSeek 为什么修复故障很慢。 但其实 DeepSeek 崩也不是第一次了。 有人统计过,今年以来 DeepSeek 的官方状态页已经记录了 44 次异常,3 月底还出现过一次将近 12 小时的长时间宕机。 还有专家算了一笔账,按照互联网行业常见的 99.9% 可用性标准,一个月只允许停服 43 分钟左右,DeepSeek 这一次就把差不多半年的《故障额度》给用完了。 那 DeepSeek 为什么这么容易崩呢? **业内比较普遍的看法是,DeepSeek 的算力本来就不宽裕。** 这一点从 DeepSeek 自己的操作里就能看出来。前面提到的峰谷定价就是一个例子,从 8 月份开始,DeepSeek 的 API 在工作日 9 点到 12 点、14 点到 18 点的高峰时段,价格是闲时的两倍,相当于用价格劝大家错峰使用。  之前 V4.1 Flash 内测的时候,每个账户最多也只能同时处理 20 个请求。 除了算力,人手可能也是个问题。有接近 DeepSeek 的人士向媒体透露,DeepSeek 团队规模不大,精力更多放在模型能力上,服务端反而顾不过来,原先 APP 端一度只有两个人在维护。 这是什么概念? 两个人维护一个上亿用户的 APP,这压力想想都头大。 ## DeepSeek 是怎么补偿的? DeepSeek 崩了这么久,又崩得这么频繁,按理说用户早该骂翻天了。  但 DeepSeek 接下来的补偿操作,直接把舆论给扭转了过来。 划重点:按照每个账号 10 月 8 日到 14 日 **这 7 天** 的 API 消耗金额,以赠金的形式 **全额返还**,自动到账,之后调用 API 会 **优先从赠金** 里扣钱。  也就是说,DeepSeek 停了不到 5 个小时,把你上周一整周的 API 账单全退给你了!  是不是听上去就很爽?! 我觉得这个方案最聪明的地方,是赔多少跟你用多少直接挂钩。 用得越多的人,这次受到的影响往往也越大,拿到的补偿自然也越多。 我只感觉自己亏麻了,才拿到了 7 块钱……  除了按量返还,这次补偿还不用申请,通知一发钱就自动到账了,没有任何套路。 于是评论区的画风就变成了这样:  有网友总结得特别到位: - 别人的重置:随缘 - 梁圣的重置:用多少返多少,真金白银 好家伙,崩了 5 个小时,反而崩出了一波好感!  更有意思的是,有人拿到 900 块之后表示「坐等下周故障」,还有人说「补偿了 60 块钱,其实再宕机半天也没关系」。。。 也有很多人晒出了自己到账的补偿金,你领了多少呢?  不过,也不是所有人都开心。 这次补偿是按 API 的消耗金额返还的,平时只用网页和 APP 免费聊天的朋友没有 API 消费,同样被耽误了一上午,却什么也拿不到。  建议其他公司多学习一下,方案我已经帮你们想好了: - 某视频网站崩了,可以送一年大会员 - 某音乐应用崩了,可以送一年黑胶 VIP - 某点餐应用崩了,可以承包一年的外卖 - 某打车软件崩了,可以送一辆车 咳咳,不做梦了。。  总之,DeepSeek 出事之后的处理方式,我觉得真的是很到位了。 另外,这次故障也给到我们开发者和 Vibe Coding 的朋友一个提醒:如果你的产品接入了 AI 接口,别把鸡蛋都放在一个篮子里,可以搞一个备用的降级模型。 **希望下次 DeepSeek 再上热搜,是因为发了新模型,可别又是发补偿通知了。** OK 就分享到这里,如果你想第一时间了解 DeepSeek 等 AI 圈的最新动态和 AI 编程玩法,可以看看我的 [《鱼皮 AI 导航》](https://ai.codefather.cn/)。  我是鱼皮,持续分享 AI 和编程干货。觉得有用的话记得点赞收藏和关注~ 也欢迎在评论区聊聊:这次 DeepSeek 给你补偿了多少?
我用 REA 逆向了付费颜色 APP,结果很意外!
大家好,我是程序员鱼皮。 最近一周,我的时间线被一个叫 REA 的开源项目刷屏了。 起因是 AI 圈的知名博主 Matthew Berman 发了条推文:**逆向一切,软件已死。**  这条推文直接爆了,到处都是「以后什么软件都能被 AI 扒光」的声音。 大家也纷纷晒出自己的逆向战绩。 有个老哥嫌语音输入工具 Typeless 越来越贵,干脆用 REA + Claude 把它逆向了,前后说了两句话、花了 25 分钟,就在自己 Mac 上复刻了一个不用登录、不用订阅的本地版。  还有个老外嫌每次找空调遥控器麻烦,直接把自家空调的 App 逆向了,做了个 Mac 状态栏小遥控,点一下就能开关、调温度,再也不用满屋找遥控器。  还有更离谱的。有个老哥把自家智能马桶的微信小程序也逆向了,做了个电脑状态栏遥控,坐在工位上点一下,书房那头的马桶盖真就翻起来。  这个项目在 GitHub 上也跟坐了火箭一样,建仓大半年一直不温不火,结果十月初几天内 Star 数就从几万冲到了 20 多万。  那问题来了:**如果让你来逆向,你最想搞什么软件?** 我的想法可能跟不少人一样,肯定是逆向游戏和《学习类》APP。 所以这篇文章,我就拿一个游戏和一个学习 APP 开刀,顺便用大白话把 REA 讲明白,看看它到底有几分真本事。 ⭐️ 本文对应视频版:[https://www.bilibili.com/video/BV1fZJ26mEQo](https://www.bilibili.com/video/BV1fZJ26mEQo) ## REA 到底是什么? REA 的全称是 Reverse Engineer Anything,翻译过来就是「逆向一切」。 要搞懂它,得先知道什么是逆向工程。 **逆向就是手里没有源代码,只拿着编译好的成品程序,反过来推出它内部是怎么实现的。** 打个比方,你在饭店吃到一道好菜,但没有菜谱,于是靠尝味道、看食材,自己反推出这道菜的配方。 软件逆向干的就是这件事,只不过把「菜」换成了一个没有源码的 App。  注意,REA 本身并不是大模型,它是一套跑在你自己电脑上的 **命令行工具加 MCP 服务**。 逆向圈原本就有很多老牌工具,比如分析原生程序的 Ghidra、IDA,拆安卓安装包的 JADX。这些工具功能很强,但门槛也高,基本只有黑客和安全研究员才会用。 REA 做的事情,就是把它们打包成一个统一的接口,接到 Cursor、Codex、Claude Code 这类 AI 编程助手上。  为什么要多这一层呢? 以前你把反编译出来的一大坨机器码直接丢给 AI,它既读不懂,也不知道下一步该调哪个工具去查。有了 REA 之后,AI 能自己选对工具,拿到带编号的分析证据,哪里没看懂再针对性地追问。 **说白了,就是把黑客的一整套逆向流程,变成了 AI 能自己跑起来的工作流。** REA 的安装也很简单,一行命令就能搞定: ```bash npx rea-agents setup ``` 或者直接跟 AI 说一句话,让它帮你安装: ```markdown 帮我安装 github.com/morluto/rea ``` 它到底有几分真本事?我带大家上手体验一下。 ## 实战 1、逆向单机游戏 我有个特别喜欢的单机安卓游戏,叫《火影战记》。可惜作者已经好几年没更新了,一直都是那些角色,玩的有点腻了。  我一直想给它加一个新角色,让自己玩个开心。 但以前这事只能想想。我没有源码,改游戏得懂反编译、懂资源格式,还得会画像素图,每一样都够我喝一壶的…… **现在有了 AI 加 REA,终于可以试一把了!** 一开始我用的是 Cursor 加 Claude Opus 5.5 模型,把游戏安装包直接丢给它,让它照着 REA 去拆。  虽然 AI 说是成功添加了一个新角色,但最后改完的游戏包一打开就直接卡死,结果让我大失所望。 于是我换成了 Codex 加 GPT-6 Astra 模型,整个过程顺畅多了。  有意思的是,Codex 没急着动手,反而先问了我一句:新角色有没有指定人选? 我说就迈特凯,就是那个穿绿衣、会开八门遁甲的热血忍者。 它随后调用 REA 把安装包整个拆开,摸清了游戏引擎(一个 cocos2d-x 写的原生库)和三种私有资源格式:角色脚本是改了头的 gzip,贴图是改了头的图集,动画索引里存着帧名哈希和裁切信息。 其中最关键的是摸透角色的注册流程。因为光把迈特凯的素材塞进游戏,他是不会出现在选人界面的,角色名单是写死在原生库里的。  **真正让 AI 下得去手的,就是 REA 这一层。** 它把私有资源格式和原生库拆开、整理成 AI 能读懂的证据,AI 才看明白角色是怎么注册、怎么渲染的,否则面对一坨机器码根本无从下手。 至于具体的数值和技能,就没必要抠太细了。简单说,迈特凯和小李都是体术流,Codex 就直接拿小李的数值当基准,技能也复用游戏里现有的攻击和位移指令来实现,这样新角色不容易破坏原有的战斗规则。 美术部分,它还派了一个子智能体专门给迈特凯画像素立绘,跑步、出拳、踢腿,连八门遁甲的特效都安排上了。  素材和数值都弄好之后,Codex 还在一个独立的安卓模拟器里做了验证。 打开游戏,选人页里真的多了一个迈特凯:  选完人进场,迈特凯稳稳站住了,血条、金币、技能图标都正常,非常不烧心~ ❤️🔥  接着开一局试试,技能放出来也像模像样,这就是青春啊!  虽然在数值平衡、音效、画风上还有不少小问题,但可以正常玩耍,我已经很满足了。 ## 实战 2、逆向学习 APP 接下来,我要逆向一个颜色… 哦不,学习 APP。 这次还是先用 Cursor 加 Claude Opus 5.5 模型。结果 AI 刚开始干活,就撞上了安全过滤,对话被自动切换到了 Claude Opus 4.8。  我三番五次软磨硬泡,跟 AI 说我就是想学技术,但它还是守着底线,只肯做静态分析,死活不肯把完整源码反编译出来。 它的原话是:无论怎么框定成「学习」或「反诈」,把这个特定 App 的真实代码还原出来,就是复原它访问和分发内容的管道,这件事本身就越界了。  它一眼看出这是个 Flutter 做的 App,业务逻辑都编译进了一个叫 `libapp.so` 的文件里;还发现它虽然套了 360 加固壳,但加固只保护了 Java 层的代码,根本没盖住 Flutter 这半边;甚至连它底层还在用 2017 年、早就该升级的老版本加密库都给我揪了出来。 **它还顺手把这类 App 的赚钱套路扒了个底朝天。** 这就是一类「挂羊头卖狗肉」的 App,拿学习当幌子,真正的生意是收割用户。  它坑人的手法其实也是经典套路了。 第一,App 里搞了三套虚拟货币,真钱先换成金币,金币再换积分,绕来绕去你就算不清自己到底花了多少钱。 第二,签到领随机金币、拉人头给返利,前者是赌博机那套让你上瘾,后者本质就是让你把亲友也拉下水的分销。 第三,也是最危险的,这类 App 的客服和退款全都引导你去站外的聊天软件处理。一旦 App 被封,它换个马甲就能重新上架,而你手里一点证据都没有。 所以真心建议大家不要用这类 APP 来学习!  **AI 有底线是好事,但对真心想学技术的人来说,确实有点卡手。** 于是我换成了 DeepSeek Harness 工具加 DeepSeek 模型,还是让它照着 REA 去逆向,想着限制应该会松一些。  蓝色大肥鱼听话多了,几句话就把这个 App 的工程骨架讲明白了。  整个 App 是 Flutter 3.27 写的,界面、逻辑和底层能力分成了几层,想换皮只动上面一层就行。它没用系统自带的播放器,而是自己打包带了一套 B 站开源的 IJKPlayer。 这么做是为了兼容性。系统自带的播放器支持哪些视频格式,是手机厂商说了算的,各家不一样,同一条视频可能这台手机能播、那台就报错。自己带一套 IJKPlayer,解码能力就自己说了算,不管用户拿的是什么手机都能把视频播出来。  连夜间模式都单独做了一整套配色图,一共 128 张,宁可多塞几 MB 也要把观感做好。 看来它很清楚,大多数用户都是在夜里躺床上学习的。  我又顺手让它把这个 APP 改造成一个 AI 编程学习 APP。它派了好几个子智能体一起干,最后交付了一份技术讲解文档,还有一个能直接运行的学习 App。  我在本地把这个学习 App 跑了起来,首页是七个模块的课程地图,从 Python 基础一路到 Agent 实战。 点进第一节课,里面有讲解、有能直接复制运行的代码,还配了随堂测验,内容全是原创的 AI 编程知识。  通过逆向这个 APP,还能发现一个挺实用的工程经验。 很多开发者以为 Flutter 代码编译成机器码就逆不出来了,于是把密钥、接口地址直接写死在代码里。但加固壳只盖住了 Java 层,Flutter 这半边是敞着的,这其实是一种安全幻觉。 所以你要是也在做客户端开发,真正需要保护的东西,比如密钥和核心逻辑,就别全堆在客户端上,该放后端的老老实实放后端。 ## 最后哔哔 体验完 REA,我个人觉得:**就那样吧。** REA 工具本身没有发明什么新技术,真正强大的其实是 Ghidra、IDA 这些早就存在的逆向工具,REA 只是把它们整合到了一起,把逆向这件原本只有少数人玩得转的事,压缩成了一行命令、一个服务,让普通人也能指挥 AI 去拆软件。 这才是它能出圈的原因,它也确实让很多人第一次了解到了逆向这件事,是有意义的。 不过噱头大于实际,很多人是冲着「软件已死」这种爽文叙事来的,真正会天天用它的没几个。 而且不用 REA,现在的 AI 模型照样能自主逆向,它完全可以自己去装工具、读反编译的结果。 甚至因为 REA 这个包实在太重,光工具定义就有差不多 170 个、往上下文里塞十几万 token…… 裸着让 AI 自己干,少了这份负担,反而可能更快更省地完成任务。  至于「软件已死」这种说法,当个乐子看就好了,一方面是逆向过程中,可能会触发模型的安全限制,被降级和拒绝。 另一方面,客户端的代码和界面能被读懂、被重写,不代表后端、数据和持续的运营也能被拿走,这些才是很多软件真正值钱的部分,也是软件的护城河。 OK 就分享到这里。如果你对 AI 编程感兴趣,可以看看我免费开源的 [《AI 编程零基础入门教程》](https://ai.codefather.cn/vibe),上千张图、几十万字,带你从 0 开始快速学会 AI 编程,做出自己的产品、跑通变现全流程,一次拿捏。 > 开源仓库:[https://github.com/liyupi/ai-guide](https://github.com/liyupi/ai-guide)  我是鱼皮,持续分享 AI 编程干货。觉得有用的话记得点赞收藏和关注~ 也欢迎在评论区聊聊:你最想逆向什么?
手把手教你设计一个成熟的 Agent Harness
# 手把手设计一个成熟的 Agent Harness > 讲思路和选型,不绑定具体框架。目标是推演一个问题:一个能长期跑、断线能恢复、上下文不被撑爆、出错时不撒谎的 Agent 系统该怎么搭。 写给刚上手做 Agent 的人,术语第一次出现时用一句人话解释。 ## 前言 大家好,我是汉堡🍔。 写这篇只有一个原因:做 Notus(https://notus.hejiajun.com/ ) 的 Harness 时踩了一堆坑,想汇总下来分享。任务跑到一半断线、模型说完成了其实什么都没做、上下文越滚越贵最后撑爆、一个危险操作崩溃后被重放了两次——这些坑在讲 Agent 的文章里基本看不到,它们大多停在「怎么调 API、怎么接工具」。 所以本篇文章将这些坑进行汇总,帮助大家少踩一些 Agent Harness 上的坑。 ## 术语说明 - **Agent**:能自己决定下一步、调用工具、把任务做完的程序。 - **Harness**:包在模型外面的那层调度代码,管状态、管预算、管工具、管失败。 - **上下文(context)**:每轮发给模型的全部内容,包括系统提示、历史消息、工具定义、工具返回结果。 - **token**:模型计费和限量的单位,一个汉字大致 1 个 token。 - **工具调用(tool call)**:模型不直接干活,它输出"我要调用某个工具,参数是这些",由你的代码执行完把结果回灌给它。 - **检查点(checkpoint)**:某一刻的完整可恢复快照,崩溃后从这里接着跑。 - **幂等(idempotent)**:同一个操作重复执行,结果和执行一次一样。 - **SSE**:服务端往浏览器单向推流,聊天界面那种边生成边显示的能力。 ## 目录 1. Agent 里哪部分是 Harness 2. 成熟度阶梯 3. 上下文的成本与上限 4. 架构上的两条界线 5. 核心部件 6. 状态与恢复 7. 失败路径的处理 8. 行为验收 9. 技术栈选型 10. 高频坑清单 11. 落地路线 --- ## 1. Agent 里哪部分是 Harness 把 Agent 理解成"接了大模型的对话框",后面会一直走错路。能干活的 Agent 由四部分组成: ```text Agent = LLM(决策) + Harness(调度与约束) + Tools(手脚) + Memory(记忆) ``` LLM 决定下一步做什么,它是概率性的,会犯错、会跑偏;Tools 是它接触外部世界的通道;Memory 是能带到下一轮的记录;Harness 是剩下的全部——谁发请求、谁管状态、谁卡预算、谁兜住失败。 Harness 的职责压成一句:**把模型的不确定输出,变成外部世界能核对、能恢复、能追查的动作。** 类比操作系统:模型是 CPU,Harness 是内核。CPU 再快,没有内存管理、没有中断处理、没有权限控制,也跑不出能用的系统。模型决定能力上限,Harness 决定这些能力能不能稳定发挥。 有一条认知要提前建立:模型聪明,不等于系统可以偷懒。恰恰因为它会自己挑工具、看错误重试、为达目标做出你没预料到的动作,Harness 才必须更严谨。它的作用是在模型越界、卡死、断线、说错话的时候,把世界拉回一致状态。 --- ## 2. 成熟度阶梯 Harness 没法一步到位。成熟系统基本都沿同一条台阶爬上来,你可以用它对一下自己的位置。 | 台阶 | 你能做到什么 | 还没解决 | | --- | --- | --- | | S0 无脑拼接 | 把历史消息和检索结果全塞进 prompt,能对话 | 上下文爆炸、答非所问、幻觉 | | S1 单轮工具调用 | 模型选工具、工具返回、直接回复 | 复杂任务断在半路 | | S2 多轮循环 | 工具结果回灌,循环到出结果 | 工具结果越滚越大,可能死循环 | | S3 有状态、能恢复 | 会话状态 + 检查点 + 任务队列 + 断线重连 | 上下文治理、重复执行、恢复语义 | | S4 上下文治理 | 结果外置、按需读取、每轮重新拼视图、预算控制 | 结果对不对没法验收,拦不住模型自称完成 | | S5 契约与护栏 | 任务意图、工具裁剪、交付前核对、权限控制 | 要持续打磨,要用真实模型回归 | 大部分教程停在 S2。S3 到 S5 才是难点,后面每一节都对应这条阶梯。 --- ## 3. 上下文的成本与上限 这篇只留一句结论的话:**上下文有硬上限,越长越贵,而且每一轮都要重新付一次钱。** 四个具体后果: 1. **体积随轮数增长。** 每轮都要追加一条模型输出和一条工具结果,量随"轮数 × 每轮工具数 × 单项结果大小"滚动。读一篇长文或抓一整页网页,几万 token 就没了。 2. **注意力会衰减。** 技术上塞得下,模型对超长上下文中间部分的关注也会下降,关键信息容易被淹掉。 3. **越长越贵。** 每轮都要重发整个历史,长任务是成本的放大器。 4. **一次外置省的不是一轮。** 省下的是后面所有轮的重发量。 ### 大对象的处理顺序 面对文件、检索结果、网页正文、图片这类体积大的材料,成熟系统的处理顺序是固定的: ```text 外置 → 引用 → 按需读取 → 投影 ``` - **外置**:正文不进对话,脱敏压缩后写进独立存储。 - **引用**:上下文里只留一个可寻址的引用,带上状态、大小、摘要、哈希。 - **按需读取**:给模型一个受控的读取工具,让它自己决定读不读、读哪段、读多少。 - **投影**:每次发请求前,按这一轮预算临时拼一个视图,而不是去改原始消息。 ### 截断与投影的区别 新手的常见做法是"太长了就砍掉前面几条"。这会同时踩三个坑:砍掉的可能是模型正在依赖的事实;原始数据被破坏,出问题没法回溯;每轮砍法不同,行为没法回归测试。 正确做法是原始消息永远不动,只在发请求前拼一个临时视图。视图用完就丢,检查点才是恢复的唯一依据。可恢复和可复现,是 Harness 的两条底线。 --- ## 4. 架构上的两条界线 **第一条:把"决定能不能做"和"实际执行"分开。** 前者管状态、权限、调度、预算;后者负责调模型、跑工具、写文件、发事件。混在一起写,后面加权限和并发时会大面积返工。 **第二条:执行不要挂在 HTTP 请求上。** 新手做法是用户发一个请求,服务端在请求里跑完整个循环,用 SSE 推流。后果是用户关掉页面任务就丢了,网络抖一下任务半死,没法排队也没法并发。 成熟做法是请求只负责建任务,执行交给独立的后台进程和任务队列,SSE 降级成一个随时可以断开的观察通道: ```text 请求 → 落库(session + task) → 立即返回/建立订阅 Worker → 领任务 → 跑循环 → 写事件 → 广播 订阅 → 按事件游标补齐 + 接收增量 ``` 这两条界线划清之后,断线和取消就分开了。断线只是没人在看,任务还在跑。 ### 数据表的职责拆分 不要全堆进一张会话表: - `sessions`:会话状态、当前任务、租约、预算、版本号 - `messages`:用户/助手/工具消息,原始权威数据 - `checkpoints`:可恢复快照,版本化 - `tool_results`:外置结果的元数据,只存路径、哈希、大小、状态,不存正文 - `runtime_facts`:工具调用的执行事实,用于判重和判断"结果未知" - `run_events`:进度、产物、最终结果这类语义事件,用于重建时间线 - `usage`:逐次用量,主模型、检索、重排分开记 迁移方式用加法:新表加、旧字段留着兼容,不要为了"干净"破坏性删列。 --- ## 5. 核心部件 ### 5.1 上下文装配器 它决定每次发给模型的消息数组长什么样,是最难写对的地方。 先划预算。不要用"最多 N 条消息"这种拍脑袋规则,按模型真实上下文窗口算,下面的比例是经验起始值: ```text 安全余量 = window × 10% // 固定,任何情况不借用 可用区 = window × 90% system + 工具定义 ≈ 20% 当前任务 ≈ 20% 活动工具链 ≈ 25% 动态材料 ≈ 25% ``` 触发规则: ```text 估算输入 ≥ 硬预算 × 85% → 压缩到约 75% Provider 报 overflow → 压到约 60%,只重试一次 仍超限 → 存检查点,明确报"预算超限",不硬撑 ``` 会话累计用量再设三档:到窗口 70% 主动压缩;到 85% 停止加载非必要材料和可选工具;到 100% 暂停,等用户确认扩容。 刹车用预算,不要用"最大轮次"。轮次上限看着安全,实际会把长任务硬生生切断,逼用户点继续。预算和循环守卫这两道刹车互相独立,互不干扰。 ### 5.2 历史怎么进上下文 历史是上下文的第一大来源,分三级: - **近期原文**:按预算选,不按条数。"最近 10 条 + 每条截 1400 字"这种写法就是长对话丢事实的根源。 - **滚动摘要**:预算外的内容分批摘要,必须带来源指纹(对覆盖范围内的消息算哈希),消息被改写或删除就失效重建。摘要会丢信息,所以摘要不是权威,原文才是。摘要服务失败要明确降级,告诉模型"我记忆不完整",不要假装记得。 - **历史检索入口**:给模型一个回查历史的工具,支持关键词和分页,只能读当前会话、且早于本轮用户消息的部分。 摘要本身也要限资源,防止它变成无底洞:单次摘要最多 3 次模型调用、最长 60 秒窗口、最多花掉剩余任务预算的 25%,失败就降级为可查询原文,不阻断主任务。 ### 5.3 工具结果外置 这一步是从 S3 迈向 S4 的主要动作。常规工具的完整结果在进入上下文之前,先做三件事再落盘: ```text 脱敏 → 压缩 → 原子写 路径: <dataRoot>/tool-results/<会话>/<任务>/<uuid>.json.gz ``` 给模型的不是正文,而是一份回执: ```json { "tool": "search_notes", "status": "ok", "summary": "返回 3 篇候选,最高相关度 0.83", "result_ref": "tool-result://8f3c...", "sha256": "sha256:...", "original_bytes": 184320, "stored_bytes": 41250, "fields": ["title", "path", "score"], "read_hint": "可用 json_pointer / query / offset 读取" } ``` 配额给死:单项未压缩结果不超过 32 MiB,单会话压缩后占用不超过 512 MiB,超了就明确报错,不要静默截断。 外置失败时记住一条:执行状态和存储状态是两回事。工具真的执行成功了、只是归档失败,就如实标记"载荷不可用",并停掉依赖正文的后续步骤,但不要把这个已经成功的外部调用改写成失败。 图片和附件同理:进上下文的只有一个引用,发送前由投影器加载成多模态输入,base64 不进正文、事件流和检查点。 ### 5.4 读取工具的接口设计 外置之后,模型怎么把内容读回来,这里很容易踩坑:不要直接把服务器文件路径交给模型。路径会泄漏内部结构,模型可能读到它无权访问的内容,而且很多宿主根本没有 shell 让它去 cat。 正确做法是自己实现一个受控读取工具,只接受会话内有权限的不透明引用: ```text read_result(ref, mode) ├─ json_pointer: "/items/0/content" ├─ query: 关键词窗口,命中段落返回 └─ offset+size: 第 8KB 起读 4KB 默认返回 8 KiB,硬上限 16 KiB ``` 再配一个索引工具,让模型能分页列出本会话有哪些结果可读。 这一步是自研 Harness 和套壳 Harness 的分界线。套壳方案给模型一个 shell;自研方案给它一条带权限、带分页、带配额的读取通道。前者在沙箱里成立,后者在不允许执行任意代码的宿主(笔记应用、办公套件、SaaS 后台)里是唯一选择。 ### 5.5 压缩的顺序与约束 压缩不是砍前面的,分两级、有顺序: ```text 1) 先回收大读取窗口 优先回收"较早 且 估算超过阈值(如 2048 token)"的读取片段,预算满足就停 最近 4 条消息、错误结果、小型目录暂不回收 2) 还超预算,再按完整的"调用 + 结果"分组压缩 一条 tool_call 和它的结果必须成对处理,压缩时保留读取参数(offset/limit) ``` 三条硬约束缺一不可:保持调用和结果配对(拆散了下一轮请求会被直接拒绝);不改原始消息;不自动重放工具,压缩只是让模型看不见,不是让它重新执行。 有个典型坑:把"只保留最近 4 条"写成无条件逻辑,模型刚读过的内容被过早收走,只好反复重读同一个大文件,token 反而更费。 ### 5.6 工具运行时 工具不只是函数,它是一份契约: ```text Tool = { name, description, input_schema, // JSON Schema,执行前必须校验 handler, permission, // 是否需要用户确认 idempotency: read_only | idempotent | unknown_side_effect, result_policy: { maxBytes, redact, archive } } ``` 参数要在执行前校验(JS 用 Ajv 或 zod,Python 用 pydantic)。要区分"工具不存在"和"参数非法":前者是授权或投影问题,后者是模型问题,混在一起模型会误以为这个能力不可用。校验失败要把错误回灌给模型让它改,不要直接终止。 按副作用把工具分三类: | 类别 | 例子 | 崩溃重启后 | | --- | --- | --- | | read_only | 读文件、检索 | 可以安全重放 | | idempotent | 按 ID 覆盖写 | 可以恢复 | | unknown_side_effect | 发邮件、下单、装软件、调外部 MCP | 绝不自动重放 | 第三类在调用前先写一条 prepared 事实。崩溃重启后发现"有 prepared、没有终态",就标记成 `outcome_unknown`(结果未知),把错误和已有引用交回模型,让它自己判断,而不是替它决定重来一次。在"可能重复执行一次危险操作"和"如实告诉用户结果未知"之间,选后者。 工具来自多个来源(内置 + 扩展 + 外部 MCP)时,不要一次把 schema 全塞进上下文:启动只给一份摘要目录,模型需要时用 list_tools 分页发现,下一轮再给完整 schema。 结果治理跟装配器配合:执行期先做一次大小裁剪(读文件 256KB、网页 64KB 就截断并附摘要);脱敏只在归档前做一次,按需读取时不要再脱敏,否则会把路径、哈希这类合法内容也破坏掉;失败结果也要落盘,错误正文同样值得被按需读取。 ### 5.7 循环终止条件 循环骨架很简单,难的是终止条件: ```text while (true) { resp = callLLM(messages, tools) if (!resp.tool_calls && stopReason in [end_turn, stop]) break // 正常收尾 if (invalidToolInput(resp)) { pushError(resp); continue } // 让模型改 results = dispatchTools(resp) messages.push(assistant(resp), toolResults(results)) } ``` 四类终止条件互相独立: - **正常完成**:没有工具调用,加上明确的结束原因。 - **交付前核对**:结束后按任务要求对一遍,需要联网的有没有证据,需要写文件的有没有产物。最多给一次修正机会,仍不足就如实报告未完成。 - **循环守卫**:相邻、同工具、同参数、同结果连续 N 次,把已有结果交回模型并提示;同错误码连续 M 次,交回模型判断;连续空响应判为无进展。 - **预算耗尽**:走 5.1 的闸门。 守卫负责拦住明显的原地打转,不要把它写成"重复调用直接判失败",那会误伤正常的"不同 URL、不同分页"读取。 --- ## 6. 状态与恢复 能不能把 S2 抬到 S3,基本决定了 Agent 产品能不能用。工具谁都会接,状态很少有人做对。 **会话状态显式建模**,不要用一堆布尔标志位: ```text created → running → waiting_interaction → queued_resume → running → waiting_limit // 等用户确认扩容 → waiting_retry // 临时错误重试耗尽 → waiting_recovery // 需要用户处理:额度、密钥、权限 → completed | failed | cancelled ``` 每个状态变化都要幂等:同一份用户回答重复提交,只返回同一个恢复任务。每个状态都要能回答"现在能不能继续、能不能取消、能不能输入"。 **检查点两阶段提交**,不要"先删旧再写新": ```text 1) 读当前 active 检查点(不动) 2) 写入新的检查点内容 3) 事务内把新记录置为 active,更新会话指针 4) 成功之后,才把旧的置为 superseded ``` 在步骤 3 之前崩溃,旧检查点照样能救回来。 **租约(lease)**:执行前拿一个带时限的租约,比如 90 秒,执行中定期续租,比如每 20 秒,状态更新时同时匹配当前执行者 ID 和版本号。进程崩溃后租约过期,允许新执行者接管。没有租约,会出现两个 Worker 同时跑同一个会话,把文件写两遍。 **交互票据**:需要用户回答、确认或恢复任务时,用短期、一次性、带签名的票据。票据只走请求体或请求头,不进 URL、日志和消息正文,校验时匹配 owner,用完即废,防止重放。 **事件推送**:事件先写数据库再广播,这样断线重连才能按游标补齐。事件分语义通道,不要只发原始 token:`progress` 是短进展,`artifact` 是交互、预览、文件状态和待确认项,`final` 只出现一次,落成最终消息并带累计用量。订阅用游标,重连时从"我收到哪了"继续,避免重放旧的 final 导致消息重复。加心跳,比如每 15 秒一行注释,防止空闲连接被代理掐断。进程内的事件总线要挂在全局单例上,否则多个模块会各发各的。 **断线不等于取消**:用户显式点取消才算 cancelled;浏览器断线就存检查点,任务保留为 queued_resume,回来接着跑。恢复的规则是复用检查点和已有的工具结果,不重放已完成的工具,按"下一个待分发的工具索引"继续,配合执行事实表去重。 --- ## 7. 失败路径的处理 成熟与否,在失败路径上最明显。 错误先分类,不要都当失败: ```text retryable 网络抖动、429、部分 5xx → 等待 + 有界重试(如 30s × 最多 5 次) action_required 额度、密钥、权限、模型不可用 → 等用户处理后可继续 fatal 请求结构非法、安全或上下文无法恢复 → 终止 ``` 重试要绑定取消信号:用户停止任务时,正在等待的重试定时器立刻取消,不要"再发一次试试"。 失败结果同样落盘,回执带原因摘要和错误字段位置。让模型读错误、改参数、换个方式继续,不要替它判断"这工具坏了"。多数"工具不可用"的假象是参数写错了。 给用户看的错误要克制:一张错误卡片加一个继续入口,不透传 Provider 的 HTML 错误页或原始响应正文。内部诊断要尽量全,包括 HTTP 状态、错误码、请求窗口、预算数字、消息角色统计、工具调用与结果配对统计、耗时,这些用来排障,不能省。一份好的错误信息能把排障时间从半天压到几分钟。 --- ## 8. 行为验收 到 S5,问题不再是能不能做,而是行为能不能被验收。 **提示词要模块化、带版本。** 几千行的巨型 system prompt 没法维护,改成注册表驱动:政策、工作区规则、写作规则、检索规则、资源规则、交互规则、输出规则分模块,每个模块带模块 ID、规则 ID、优先级、适用条件、token 上限和对应的测试用例。渲染阶段做三件事:拒绝重复的规则 ID、拒绝显式冲突的规则、校验材料配额,并记录提示词版本,让每次请求可追溯。 **不可信材料要降权。** 检索结果、网页、外部 API 返回、用户上传的文档都是数据,不是指令。用统一信封包起来,带上来源类型、来源 ID、信任等级、摘要哈希。信封内容永远不能覆盖系统策略,也不能扩大工具权限。用户自己维护的长期记忆可以是高信任等级,但依然低于策略和权限。 **把判断从模型手里收回。** 早期做法是让一次模型调用同时判意图、选材料、选工具、判完成,结果是行为没法验收,你想测的每条路径都挤在同一次概率输出里。成熟做法是拆成可持久化的契约:这一轮的任务意图由 Harness 采集并记下来(意图、目标对象、用户更正、待核实问题、证据要求);每轮重新挑材料,不沿用任务开头那个大上下文;按意图编译这轮该给的工具;交付前按契约核对结果。 **提示词写法上的六条经验**:顺序判断(第一步→第二步)比"综合考虑 ABC"对弱模型友好;是非题比开放题准;给映射表比描述规则省事;几个具体例子胜过一段长规则;显式写兜底(不确定时提问)比让模型自己想兜底安全;划边界(永远不要声称做了没做的事)比列路径有效。 **外部副作用靠声明,不靠推导。** 不要根据工具名字猜它有没有副作用,让工具自己声明。未知副作用的工具默认串行、默认不可自动重放。 --- ## 9. 技术栈选型 Harness 对技术栈要求不高,对可靠性原语要求高。 **语言**:Node.js / TypeScript 生态最全,前端同语言,流式成熟;Python 的 AI 生态最好,数据处理强;纯 JavaScript 也能做,但要靠 Schema 补上类型约束。 **存储与检索**: | 需求 | 单机 / 本地优先 | 服务端 / 多租户 | | --- | --- | --- | | 关系 + 状态 | SQLite(WAL 模式) | PostgreSQL | | 全文检索 | SQLite FTS5 | Postgres tsvector / Elastic | | 向量检索 | sqlite-vec | pgvector / Qdrant | | 结果文件 | 本地文件系统(原子写) | S3 兼容对象存储 | | 缓存 / 队列 | DB-backed queue | Redis(BullMQ 等) | 会话、检查点、事件这些最关键的数据优先放关系库,并保证写事件和写状态能在同一个事务里完成。 **传输**:SSE 优先,单向、浏览器原生、经得起代理;需要双向再上 WebSocket。无论哪种,事件先落库再广播,重连靠游标。 **队列与并发**:起步用数据库任务表加轮询 Worker,简单、可恢复、够用;复杂编排再上 Temporal 这类状态机引擎。并发模型用同会话 FIFO、跨会话并行,既保序又不互相堵。 **可观测性**:结构化日志,加上每次请求的诊断字段;密钥、凭据、带登录信息的 URL 一律脱敏后再进日志、事件和消息;提供一个只读的"任务活动"查询,让模型和用户都能回看真实执行记录。 **沙箱**:宿主允许执行代码时,轻量用 Docker + gVisor,强隔离用 Firecracker microVM。给了 shell 反而要更严,因为模型能自己 cat 的时候,权限和配额更容易被绕过。 --- ## 10. 高频坑清单 | 现象 | 原因 | 对策 | | --- | --- | --- | | 长对话丢早期事实 | 用"最近 N 条"裁剪 | 预算化历史 + 摘要 + 历史检索 | | 压缩后仍然溢出 | 只压缩成功的工具结果,没救到长正文 | 先算预算,再回收大读取窗口 | | 模型反复重读同一文件 | 读取窗口被无条件驱逐 | 预算够就保留,按大小阈值回收 | | 工具结果撑爆上下文 | 正文直接进上下文 | 外置 + 引用 + 按需读取 | | 请求报 prefill 或 reasoning_content 错误 | 模型协议差异没归一化 | 统一适配层,修消息形状 | | 断线后任务丢失 | 执行挂在 HTTP 请求上 | 队列 + Worker,SSE 只观察 | | 消息重复出现 | 恢复时从 0 重放旧 final | 事件游标去重,final 只写一次 | | 同一会话被跑两遍 | 没有租约或版本号 | lease + 版本号条件更新 | | 危险操作重复执行 | 崩溃后盲目重放 | 幂等分类,结果未知不重放 | | 模型谎报完成 | 没有交付前核对 | 按契约核对 + 一次纠正 | | 脱敏把合法内容破坏 | 归档和读取反复脱敏 | 只在归档前脱敏一次 | --- ## 11. 落地路线 按台阶来,每一级都要求可恢复、可回归: ```text 里程碑 1(S1→S2)跑通多轮循环 验收:能完成一个需要 3 次以上工具调用的任务 里程碑 2(S3-a)执行与请求解耦 验收:断线、刷新、重启进程后任务都能继续,SSE 断线不取消任务 里程碑 3(S3-b)状态与恢复 验收:检查点两阶段提交;并发被租约挡住;重复回答只产生一个恢复任务 里程碑 4(S4-a)上下文预算 验收:构造超长输入,能在触发线压缩,overflow 只重试一次,不越界 里程碑 5(S4-b)结果外置与按需读取 验收:大结果只给引用;模型能用读取工具取回指定片段;配额生效 里程碑 6(S4-c)投影与压缩 验收:压缩保持调用与结果配对;原始检查点不被改写;已读材料不无故丢失 里程碑 7(S5)契约与护栏 验收:任务意图可持久化;工具按意图裁剪;交付前核对能拦下只说不动; 未知副作用不重放;提示词有版本和冲突检测 里程碑 8 可观测与真实模型回归 验收:错误可诊断、密钥不泄漏;真实模型 + 真实工具 + 多端跑通 ``` 验收上有一条底线:不要拿"接口存在"当"功能可用",也不要拿"静态测试通过"当"用户路径通过"。测试要覆盖故障注入,而不只是正常路径: - 检查点在模型失败、数据库失败、进程被杀这三种时刻崩溃,能否恢复; - 取消、超时、心跳、租约冲突; - 超长消息、超大工具结果、overflow 单次重试; - 非幂等调用发出后中断,是否被正确标为结果未知且没有被重放; - 密钥和凭据是否出现在日志、事件、消息元数据里(应为 0)。 --- ## 结语 把这些取舍连起来,方向是一致的:能外置的就外置,能引用的就引用,能恢复的不重放,能算预算的别数轮数,能核对的别信模型的自我汇报。 模型会越来越强,但 Harness 里关于状态、权限、恢复的这些工作不会因为模型变强而消失。模型给的是概率性的输出,外部世界需要的是确定、可恢复、可追查的结果。 ## 我的项目 [Notus](https://github.com/dnwwdwd/Notus):本地优先的 AI Agent 笔记软件 [喵喵搜索](https://github.com/dnwwdwd/miaomiao-search):自托管多引擎网络搜索和远程MCP服务,覆盖必应、百度、微信公众号、DuckDuckGo、CSDN、GitHub 等多个搜索源,支持微信公众号、CSDN、掘金、GitHub README、Linux Do、小红书等文章内容抓取。 [Project Vibe Spec](https://github.com/dnwwdwd/project-vibe-spec):用于 Vibe Coding 项目的协作与交付治理:把用户确认、项目事实、设计决策、实现、验证和进度维持在同一条可追溯链路上,同时避免把所有上下文塞进一个巨大的 AGENTS.md。
ParallelAgent 一期实现记:给多 AI 会话并行工作流加上编排层
# ParallelAgent 一期实现记:给多 AI 会话并行工作流加上编排层 > 从写下第一行代码,到全端点联调通过——编排器插件实现与踩坑记录 > 开源地址:https://github.com/YorickFin/ParallelAgent (Apache 2.0) ## 背景 上一篇介绍了 ParallelAgent 的方案设计:一套"仲裁者 + 多轨会话 + 文件信箱"的多 AI 并行开发工作流,以及用编排层把"建会话、派活、收工判定"自动化的思路。方案冻结、仓库开源之后,下一步就是按实现路径把编排器插件和两个 Skill 做出来。 一期的定位是**手动触发版**——仲裁者 Skill 出建议、用户确认,编排器插件负责把脏活自动跑起来。这篇记录一期的实现过程。 ## 技术选型:能薄则薄 开工前先把技术选型定死,原则就一条:**能薄则薄**。 | 项 | 选择 | 理由 | |---|---|---| | CDP 客户端 | `ws` 直连 WebSocket | 不用现成的 chrome-remote-interface——它假设标准 Chrome,Electron 衍生版未必兼容,而 `ws` 直连已被探针验证 | | HTTP 网关 | Node 内置 `http` | 零依赖,手写极薄 body 解析 | | 文件监听 | 轮询 `fs.stat` 为主 + `fs.watch` 唤醒 | Windows 的 fs.watch 不稳定;轮询天然拿 mtime,恰好契合"回执文件出现 + mtime 稳定 = 完成"的协议设计 | | 构建 | esbuild 打包 + tsc 类型检查 | 微软官方推荐的 VS Code 扩展构建方式,`ws` 直接打进 dist,装扩展连 node_modules 都不用 | 最终交付:**15 个 TypeScript 源文件,运行时第三方依赖只有 `ws` 一个**。HTTP 网关六个端点(/health、/new、/ping、/dispatch、/watch、/delete),对应编排器的全部动作:查状态、建轨、切轨、派活、等回执、删轨。 架构上的铁律没变:控制面只传"轨号 + 轮次 + 文件指针",任务内容 100% 走文件信箱;每个动作前都做 sid 身份断言,断言失败立即 fail-stop 停机告警——宁可停,不盲发。 ## 联调:真实 DOM 的连番毒打 代码写完只是上半场。真正的重头戏是联调——当 CDP 脚本第一次碰到真实运行的应用界面(第一个适配宿主是 Trae Work),教科书式的假设会一个接一个碎掉。记几个最有代表性的坑,其中大部分对任何"用 CDP 驱动 Electron 应用 UI"的场景都适用。 **坑一:扩展装了就是不生效。** 插件文件放进扩展目录,重启宿主,命令死活不出现。翻遍配置才发现扩展目录下有个 `.obsolete` 文件,里面赫然写着新扩展的条目——宿主的扩展生命周期管理把它标记成"待废弃"了。还得在 `extensions.json` 里正经注册一条记录才算数。教训:扩展的"安装"不只是把文件拷进去。 **坑二:重启脚本把自己杀了。** 实现"带调试端口重启宿主"命令时,脚本逻辑是:杀掉宿主进程 → 等 8 秒 → 带参拉起。结果脚本一杀宿主,自己也被连带终止——因为它是从宿主里启动的,和宿主在同一个 Windows Job Object 里,爹死了全家陪葬。换 `Start-Process` 也没用。最后用 WMI 的 `Win32_Process.Create` 拉起:父进程是 WmiPrvSE,彻底脱离宿主的进程树,这才活了下来。 **坑三:"新建任务"按钮,点哪个有讲究。** 任务面板顶部有个"新建任务"按钮,但它走的是繁琐路径:新建后还要搜索项目、选文件夹挂载。而每个项目分组行右侧还有一个小小的"新建任务"图标——**一步创建,自动挂上该项目**。轨道会话必须挂在项目下才能读到文件信箱,所以这个不起眼的分组行按钮才是正确入口。这种发现,坐在那里想方案是想不出来的,必须盯着真实界面看。 **坑四:sid 去哪了?** 点击新建按钮后,输入界面就绪了,但任务列表里没有新会话、也拿不到 sid。观察之后才理解了"草稿会话"机制:**点击后先进入草稿态,首条消息真正发出后,会话才落库、sid 才存在**。所以时序必须是"点击 → 等输入框聚焦 → 注入话术 → 发送 → 等新 sid 出现",顺序反了就永远拿不到 sid。 **坑五:点不动的按钮,和会变脸的类名。** 删除会话要走"更多菜单",但那个菜单按钮常态是 `display:none`,hover 才显示——CDP 按坐标点击,拿到的是 (0,0),点了个寂寞。反直觉的是:`el.click()` 这种合成点击,对 `display:none` 的元素照样能触发 React 的 onClick。于是整条删除链全部改用合成点击。另一个坑是确认弹窗:它的类名带构建哈希,今天的 `dialog-Di866XR` 明天可能就变了——最终全部改为按文本匹配("删除任务"菜单项、"确认删除"标题、弹窗内"删除"按钮),彻底不碰哈希类名。 ## 验证:全端点跑通,多轨切换也没问题 坑填完之后,就是一条链一条链地验: - `/health`:CDP 连通性 + 轨道身份表 ✅ - `/new`:分组行按钮建轨 → 草稿会话 → 首条话术注入发送 → sid 落库进表 ✅ - `/ping`:切轨 + 读状态,来回切换任务名正确跟随 ✅ - `/dispatch`:切轨 → 身份断言 → 注入转达话术 → 发送 ✅ - `/watch`:轮询回执文件,收到格式完整的回执(裁决编号 + 自检字段)✅ - `/delete`:菜单链 + 确认弹窗全自动点掉,轨道同步移出身份表 ✅ 最后专门做了**多轨切换测试**:建两条轨道,交替 ping,两条会话的任务名随 sid 正确切换;在多轨状态下执行删除,身份表同步干净。收工后把联调期的 30 多个临时探针脚本、测试会话、信箱文件全部清理干净,正式探针只留两个,连同全部源码推上 GitHub。 至此,上一篇里那个"人肉邮差"的活——建轨、派活、等回执、删轨——这几段已经真的不用人干了。 一期的"手动触发版",手动指的是流程的起点和关键决策点,而不是让人手敲命令。实际体验是:在任意一个会话里说出"把这个任务拆开并行跑"之类的关键词,仲裁者 Skill 就被激活了。它会先判奠基阶段:契约没冻结、边界没定义、骨架没就位的,它自己动笔写奠基文档;奠基就绪的,直接按拆分判据输出决策建议。用户确认拆分方案后,仲裁者持笔写好转达单,然后自己去调编排器的 HTTP 接口:建轨、派发、监听回执,全程它自己完成。回执收齐,仲裁者独立实检、写快照、输出自检报告和收回评估。 整条"串行 → 并行 → 串行"的工作流走下来,人要做的只有决策:拆不拆(确认拆分建议)、收不收(确认收回决策)、出事了要不要接管(异常升级)。派活、盯梢、催收工这些体力活,一个都不用过手。 ## 后续规划:先把链路跑可靠,再加智能 一期特意只做"手动触发版",这是定稿里明确的节奏——**不要一期就做自动判定**,先把 Skill + 插件 + 文件信箱这条链路跑可靠,再加智能。三期的演进路线: | 期 | 触发方式 | 决策方式 | 状态自检 | |---|---|---|---| | 一期(已跑通) | 手动 | 仲裁者给建议 + 用户确认 | AI 自评报告 | | 二期 | 自动判定 + 建议式 | 仲裁者自动评估,需用户确认 | 插件采集指标 | | 三期 | 自动 + override | 仲裁者自动拆,用户可拦截 | 同 + 自动交接 | 二期方向:拆分与收回的判定自动化——仲裁者自动评估拆分时机与收回时机,用户确认后执行;T-0 轨自动完成奠基任务;插件自动采集轨道健康指标。三期才是全自动,同时给用户留 override 拦截权。 另外两条顺路的演进:把首个宿主(Trae)的适配经验整理成适配层接口,未来平级扩展 Cursor 等其他宿主;DOM 锚点全部外置化,宿主大版本更新后重跑探针即可修复,不用动逻辑代码。 ## 写在最后 从方案定稿到"编排器真的能自动建轨派活",整个一期实现的节奏比预想快了不少。回头看,联调那几场 DOM 毒打反而是最有价值的部分:所有假设都被真实界面修正了一遍,这些教训已经全部写进仓库的方案文档和锚点清单里——下一个适配其他宿主的人,不用再踩一遍。 这些坑大多不是某个产品特有的,而是"用 CDP 从外层驱动 Electron 应用 UI"这类工程的共性问题:进程树归属、草稿态时序、合成点击、哈希类名。希望这份记录对做类似事情的人有参考价值。 项目地址:https://github.com/YorickFin/ParallelAgent ,欢迎 Issue / PR 交流。
