尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Atlas如何「嗅探」Agent使用的模型?atlas-acp的model_sniff实战拆解

发布时间:2026/9/18 22:22:58

资讯中心
01
ARTICLE

Atlas如何「嗅探」Agent使用的模型?atlas-acp的model_sniff实战拆解

Atlas如何「嗅探」Agent使用的模型?atlas-acp的model_sniff实战拆解
Atlas如何「嗅探」Agent使用的模型atlas-acp的model_sniff实战拆解【免费下载链接】atlasSource control for agents. Use multiple coding agents, track their changes and query them in one place项目地址: https://gitcode.com/GitHub_Trending/atlas115/atlasAtlas 是一款「面向 AI 编程 Agent 的源代码管理工具」你可以在同一处同时使用多个 Coding Agent如 Claude Code、Codex、OpenCode 等统一追踪它们对代码库的改动并随时查询。它的 ACP 客户端核心位于 crates/atlas-acp/其中model_sniff模块解决了一个很隐蔽的问题——如何准确「嗅探」出每个 Agent 当前使用的模型列表让 UI 上的模型选择器永远有货可显示。问题背景为什么模型列表会「消失」Atlas 通过ACPAgent Client Protocol与各个 Agent 子进程通信按行分隔的 JSON-RPC 消息走 stdin/stdout。模型信息最初藏在session/new新建会话和session/load恢复会话的响应里形如{ currentModelId: opencode/grok-code, availableModels: [ {modelId: ..., name: Grok Code} ] }但 ACP v1 规范发生了漂移NewSessionResponse结构体悄悄删除了顶层models字段模型选择被挪进了configOptions。新版 Agent如 Kilo没问题——crates/atlas-acp/src/schema.rs 里的model_blob_from_config_options会把configOptions归一化成统一的模型列表格式。可问题在于OpenCode 1.3.x、Cursor 等已发布的 Agent 仍在使用旧方言坚持返回顶层models对象。类型化的反序列化器会把这个字段直接丢弃——结果就是模型选择器渲染不出来用户看到的是这个 Agent 不能切换模型。 详见 crates/atlas-acp/src/model_sniff.rs 文件头部的注释完整记录了这段设计动机。核心思路不 Fork 协议在「线路」上偷听Atlas 没有去分叉 ACP schema而是采用了更轻量的方案——在原始 JSON-RPC 线路上挂钩子挂调试钩子ACP 的AcpAgent::with_debug提供逐行回调能看到写入 stdin 和读自 stdout 的每一条原始消息。在 crates/atlas-acp/src/driver.rs 中Atlas 把每个方向的行分流给ModelSniffer的两个观察方法。记住请求 IDobserve_outgoing监听发出的session/new/session/load请求记录其 JSON-RPCid数字和字符串统一转成字符串作键。匹配响应抓取observe_incoming收到响应时按 id 匹配从result.models里把整个模型 blob 摘出来按 session id 暂存。取用即销毁注册表在组装NewSessionInfo时调用take(session_id)取走 blob——读取即消费避免重复填充。整个实现只有 crates/atlas-acp/src/model_sniff.rs 一个文件核心结构体是ModelSniffer字段作用pending在途的session/newNone/session/load会话 ID请求表captured已抓到的旧方言modelsblob按会话 ID 索引等待注册表取走工程细节四个容易踩的坑都被填上了model_sniff的代码值得细读因为它把协议嗅探里所有边缘情况都处理干净了内存有界pending超过 32 条、captured超过 64 条时直接清空。一个卡死不回复的 Agent 不会让映射表无限泄漏。session/load响应不带会话 IDsession/new的响应会返回新生成的 id但session/load只回显模型列表。所以嗅探器在发请求时就把params.sessionId存下来响应没带 id 时兜底使用见 model_sniff.rs 的注释。无关流量免疫无 id 的通知如session/prompt、未跟踪的 id、错误响应、甚至 Agent 启动时打在 stdout 上的 banner 文本如opencode v1.3.15都会被安全忽略不会 panic。读取即消费take()用remove实现同一 blob 不会被折叠进NewSessionInfo两次。测试代码同样精彩——model_sniff.rs 里用 OpenCode 1.3.x 的真实响应报文做了逐字复刻4 个测试分别覆盖常规抓取、session/load兜底 ID、无关流量与错误响应。想跑一遍完整链路可以直接用示例工程 crates/atlas-acp/examples/smoke.rs它同样演示了with_debug钩子打印每条进出消息的用法。嗅探结果如何送达前端抓到 blob 只是上半场后半段是「接力」注册表兜底crates/atlas-acp/src/registry.rs 的new_session里若类型化响应没给出模型info.models.is_none()就从model_sniffer取嗅探到的 blob 补上——旧方言 Agent 的模型选择器因此得以正常渲染。前端缓存加速模型列表本质上是静态的只有 Agent 升级才会变但首次获取需要等待进程启动 握手约 3–4 秒。src/features/chat/lib/acp-models-cache.ts 把每次确认的列表持久化到 localStorage切换 Agent 时立即乐观填充模型选择器。后台预热src/features/chat/lib/warm-acp-models.ts 会在后台为其他用过的 Agent 开一个一次性会话刷新缓存带 7 天 TTL避免每次启动都白开会话让这个嗅探 缓存的闭环对用户完全无感。小结一段不到 130 行的协议考古model_sniff是在协议规范与现实之间打补丁的优秀范例不动 schema不 fork 协议只在原始线路上旁路监听侵入性最小️防御式编程有界缓存、ID 归一化、ID 兜底、脏数据免疫全部就位端到端闭环从 Rust 侧嗅探 → 注册表兜底 → 前端缓存/预热UI 体验始终秒出模型列表。对想维护多 Agent 工具链的开发者来说这套wire tap线路窃听手法通用性很强凡是类型化反序列化会丢字段、而你又不想受制于某个库版本的场景都可以照此办理。核心源码就在 crates/atlas-acp/src/model_sniff.rs配合 crates/atlas-acp/src/driver.rs 的钩子接线一起读半天就能吃透。【免费下载链接】atlasSource control for agents. Use multiple coding agents, track their changes and query them in one place项目地址: https://gitcode.com/GitHub_Trending/atlas115/atlas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。