这一版做
- 探这台机器装没装
claude/codex、装在哪、什么版本 - 找到每个 CLI 自己的那几个目录(配置 / 历史会话 / 命令),记下位置 + 一个小标记(以后看有没有被改过)
- 能针对某一个 CLI 点一下「重探一遍」;daemon 启动时自动探一次
- 处理不同系统的路径差异(做到哪一档见 ⑦)
- 把「算路径」这段写成可复用的小工具
available=true,对外只报事实,不碰界面、不管存数据库、不改公共代码。这是个独立任务,跟各 provider adapter 互不依赖;这一版只做探测,改配置(往文件里写)是确认要做的,但放后面。
这份是咱俩一起对的,主要把分工说清:哪块你来、哪块地基来、不够用了一起调。
没跟过前面讨论的人(协作方 / LD)先看这段,补齐上下文。
Eyrie 要统一接入多个 agent CLI(claude、codex…),每个都能在 UI 里被选来开会话。但有个基础问题一直空着:这台机器上到底装没装某个 CLI、装在哪、什么版本、配置在哪? 现在系统答不上来 —— 一个 provider「可不可用」目前只是占位:只要它被启用、且有对应 adapter 就当可用,并不代表机器上真的装了;版本字段有,但没人往里写。于是 UI 没法诚实告诉用户「claude 在这台机器上装了没、是哪个版本」。这个模块就是来补这块真实探测。
agent_providers 表、ProviderModule、detectAll();但「可用」就是上面那个占位,没探真实安装。providers/claude/),codex 在路上 —— 这俩是各自的「专项适配」,跟本模块是两件独立的事。agentInfoJson(放版本等)/ capabilitiesJson / capabilitiesUpdatedAt(上次刷新时间)三列建好了,全仓没人写。只做只读探测(细节见 ①);改配置(自定义第三方 API 那类写操作)确认要做、但放本期之后(⑧)。
先把范围对齐:这样你清楚哪些是这次要做的、哪些是故意先不做的 —— 不会多做,也不用担心漏了。
claude / codex、装在哪、什么版本用户说的「发现」其实是三件事。它们用的是同一批底层本事(算路径、跑命令探一下、把结果记下来再判断要不要重探)—— 所以才值得单独做成一块。
查这台机器有没有这个 CLI、在哪、什么版本。不同系统找起来差别最大;装了好几份要全列,不偷偷只挑一个。
只「找到位置 + 记个小标记」,不打开看里面写了啥。难点是不同系统的家目录写法、WSL 下能不能看到。
之前探的结果不能一直是老的。这一版靠「手动点重探 + 启动探一次」;自动监听放二阶段。
说到底就三块:模块自己知道「怎么探每个 CLI」→ 探一遍输出「探到啥」→ 能「重探」。下面写的是大概有哪些信息,具体怎么定义你自己来。
发现模块内部就知道 claude/codex 怎么探:命令叫 claude/codex、版本用 --version 问、那几个目录在哪。就是模块里的几行数据,不用谁喂、也不发给 provider 层;外加一个小函数把版本号摘出来。
装了就把对应 provider 标 available=true;再带上用的哪条路径、装了好几份就全列、版本号、那几个目录在不在 + 小标记、什么时候探的、没探到是哪种原因。全是事实。
启动探一次;针对某个 CLI 点重探(同时点好几下,合并成只跑一次,不重复开进程);要关的时候能干净地停。
这四条是这块东西的灵魂,也是 review 时咱最该一起守的。其余内部怎么搭,你全自由。
| 规矩 | 为什么 |
|---|---|
| 只报事实,不下「能不能用」的结论 | 引擎只说「命令找到了、版本是多少」;「这到底算不算能用」是地基那边定,不在引擎里。 |
| 探的时候出错,就当「不可用」,绝不让错误冒出来把整件事搞崩 | 机器状态什么样不好说,一次探测出岔子,不能连累整个流程。 |
| 所有跟外部打交道的动作都能换成假的(读文件 / 跑命令 / 看是什么系统 / 取时间) | 这样测不同系统的行为时,不用真去找一台 Windows/Mac,在假环境里就能测。 |
| 不去读懂配置里写了什么 | 里面写了啥是各 CLI 作者的知识;引擎只负责找到它、记个小标记。 |
整块东西交给你来建,地基这边做公共接口和接线。简单分一下:
引擎本体 + 测试 + 自己用的类型,全在 agent/discovery/ 里;里面怎么分文件、定义什么类型、测试怎么写,你说了算。
公共接口(类型定义 / 各 provider 声明)和接线(把你的结果接进系统、存起来、加「重探」入口、加边界检查)—— 这些你不用动。
做着发现跟地基的接口对不上(比如探到的结果想多带个字段、registry 那边没接),喊一声,咱一起补。
claude/codex 要探哪些(命令名、目录)就是模块自己的一张小数据表,不发给谁;模块本身通用,加新 provider 就往表里加一行 —— 你不用等任何人,直接开工。
这几件都是地基这边的活,不用你写。摆出来是让你知道「我探出来的东西会被这么用」—— 对一下,接口才严丝合缝。其中「写回」那条是我们这边要补一下的,标出来了。
| 地方 | 现在啥情况 | 我们这边会做 |
|---|---|---|
| 探出来的结果怎么接进去 | 已经有读「版本」的地方,但还没人往里写 | 把你的结果接进去;「这算不算能用」由地基这边判断,不用你管 |
| 写回数据库 需调整 | ⚠ 现在只能整行覆盖,没有「只改几列」的写法 | 我们要加个「只改探测结果那几列」的写法,不然会把用户自己改过的命令/环境变量/密钥冲掉 —— 之前踩过 |
| 「重探」入口 | 还没有 | 在 service 加个重探方法 + 一个 tRPC 调用(注:现在走 tRPC,不是老的 HTTP 接口) |
| 边界检查 | 已经有两条 | 再加一条:引擎不去 import provider 内部,provider 也不 import 引擎实现 |
这是唯一需要先定的 —— 这几条定了,你就能直接开工。下面是地基这边的倾向,咱对一下,有不同想法随时提。
| 问题 | 倾向 | 为什么 |
|---|---|---|
| Windows(原生)这次做不做 | 先不做,先把 Linux + Mac 弄好 | 我们现在开发就在 WSL/Linux 上;Windows 原生那套(路径、注册表那些)是跨系统里最费劲的大头。接口先留好「换系统」的位子,以后补不费事 |
| 文件自动监听这次做不做 | 先不做,放二阶段 | 这次就「手动点重探 + 启动探一次」;靠监听去发现命令「装上/卸掉」不现实(要盯的目录太多) |
| 探出来的结果存哪 | 存数据库 | 列已经有了、本机数据库也没有跨机器的麻烦、重启不丢 —— 但要走上面那个「只改几列」的写法 |
自定义第三方 API 渠道(不是所有人都走官方渠道)是确认要做的真需求,但这一版不做。顺手把它跟探测的关系讲清,方便将来续上 —— 也让你知道现在为什么不碰它。
找到配置文件 + 记小标记,顺便发现是不是被外面改过。
放在各 CLI 适配器里的单独本事:读出来 → 改 → 写回去,带校验、先备份再整体替换、绝不碰自己看不懂的字段。
写完文件变了 → 顺手触发一次重探。
这两边共用探测导出的「算路径」那套小工具,串成「读 → 写 → 读」。所以这次把「算路径」那块做扎实,就是给将来的写功能铺好路。
几个一开始就对齐的点,省得做到一半想岔了。有别扭的随时提。
我能改公共接口(types / registry)那些吗?
接线是地基的活,这块你不用碰;接口不够用喊一声一起补。
「能不能用」谁说了算?
你只报「命令找到了」这个事实;合不合成「能用」是地基这边判断,不归你。
探的时候出错怎么办?
就当「不可用」,顺便说清是哪种原因,千万别让错误冒出来。
配置文件里写了啥,我要看懂吗?
不用,只要找到它、记个小标记。内容是各 CLI 作者的知识。
第三方 API 那个要我做吗?
这次不做。那是以后的「写」功能,放在各 CLI 适配器里,跟你共用「算路径」那套工具。
版本怎么拿?
去跑一下那个命令问版本(给个超时,比如两三秒);从打印出来的字里摘版本号,用你那份说明里的小函数。跑命令、超时这些引擎管,你不用碰进程。
一个 CLI 装了好几份咋办?
全列出来,标一下用的是哪个,别偷偷只挑一个。
怎么测不同系统?
把读文件、跑命令这些都换成假的,在假环境里测,不依赖跑测试的机器是什么系统。