委派这一版从一张清单变成一张图:谁在等谁、谁在排队等名额、哪一步是真跑过的,都画了出来,点一个节点就落到它对应的那次调用上。待发队列也换成了内核持有的那一份。自 2.6.0 起 23 个提交。
新增
运行图
- 此前面板只能数出「四个子代理在跑」,说不出其中哪个在等哪个——因为它拿到的那份清单早就把结构丢掉了:
depends_on活在一次 Execute 调用里,从没离开过进程;落盘的 sidecar 只记了一条父子链接;事件流靠 id 前缀暗示其余部分。结构现在由内核发布(internal/agentgraph),不再由前端从形状上猜。 - 一列就是一个秩:里面的节点在那一刻都可以跑。宽度是并发、长度是链条——这正是清单渲染不出来的区别。
- 边按线型区分而不是颜色:实线实心箭头表示上游的答案进了下游的上下文;虚线空心箭头表示只排了先后、什么都没传。消融测量臂产出的正是后者,两种画成一样就等于说这两次运行是同一次。复用是节点上的标记,因为被采纳的条目根本没跑。状态在卡片上是一个词,不只是一个颜色。
- 排版不再只有秩。此前节点在列里的行号由增量到达顺序决定,连线毫无理由地交叉,跨列的边直接压过中间的卡片,同一次运行重画一遍还不一样。现在补上了 Sugiyama 缺的两步:按邻列行号中位数扫排(只保留让交叉数下降的那一轮),长边在它跨越的每一秩预留一条细行,于是它从卡片之间穿过而不是压上去。列按最高的一列居中,而不是从顶端吊下来——孤零零一个节点此前读起来像「跑得早」,其实是「只有它」。
- 点一个节点就跳到那次调用本身:它的参数、输出、周围的推理。此前只有用户消息在 DOM 里带锚点,因为只有回退轨需要找东西。工具卡片现在带上图里称呼它的那个 id,嵌套的子调用也带——扇出的节点实际就住在那儿。
一个节点会说它什么时候跑的、在等什么
- 图上早就声明了
StartedAt/EndedAt,却从来没有生产者填过,于是每个消费者的时间回退分支都是死代码,一次运行的先后只剩下「增量碰巧按什么顺序发布」。 - 「在等名额」和「拿到名额」此前是同一个词。被会话并发上限限流的扇出,和所有条目同时开跑的扇出,画出来一模一样——而这两者的区别,正好决定把上限调高有没有用。现在
StateQueued与QueuedAt分开,详情条上「等名额」和「实际运行」并排。 - 一个条目在它自己结束的那一刻就结束,而不是等整组结束。长扇出此前会把每个跑完的 worker 一直画成还在跑,直到最慢的兄弟返回——那正是有人在盯着看的全部时间。
待发队列面板
- Studio 早就能在一轮进行中插话,但看不见队列:屏幕上那些待发行是客户端自己造的,只说明「这个窗口发过什么」。刷新一下就没了,而条目还在清单里,仍然会在下一个工具边界送出去。CLI 排的一行、另一个窗口排的一行,从来没出现在屏幕上过。
- 内核有十个 inbox 端点,前端只读了三个。编辑、重排、重试被拦下的条目、重新冻结它引用的文件、暂停投递——全都存在,只是没有入口。composer 上方这块面板就是入口。
- 队列的到达方式和工作区树、检查点列表一样:事件只说「它动了」,内容整份读回。事件本身不带快照——带上就等于让每个客户端的队列取决于它碰巧收到了哪些帧,漏一帧的重连会留下一块过期的面板。
菜单栏 / 任务栏图标就是输入框里那个 R
- 此前画的是一个带缺口和角标的圆角方块——这个记号在产品里别处不存在,于是托盘成了 Reasonix 唯一一处用着另一个 logo 的地方。现在是 composer 那个 R,原样搬过来。
- 状态只改颜色,每个色沿用配色里它唯一的含义:灰是中性,蓝是它自己在跑,琥珀是需要你。明度不取浅色也不取深色主题的值——通知区的底色这个进程问不到——三个色对白底和近黑底都不低于 3:1。
修复
- 多次双击启动图标会开出多个实例(#9414)。Studio 从来没配过单实例锁,于是每次双击都在同一个数据目录上再起一个进程,几个窗口互相抢同一批会话文件的写租约。锁按数据目录标识,而不是按可执行文件:安装版、便携版、canary 写的是同一批会话,必须互相认得;显式设
REASONIX_HOME仍然是独立实例,那是并行跑两个的正当方式。 - 新开的对话偶发不继承工具批准档位(#9414)。新面板的档位读的是 hub 里排第一的那个运行时。于是把设成「自动」或「全放行」的那个对话关掉,下一个就回到「询问」——对一个你已经放行过的工具再弹一次框,屏幕上没有任何解释;把所有面板都关掉,更是没人可读了。现在由 hub 持有这个立场:宿主接管运行时时播种,composer 切换时写入(同一次切换本来就已经写进配置供下次启动读),与哪些面板还开着无关。
- 拖进来的 .md 被当成图片(#9412)。
droppedRef.Image带着omitempty,而false正是 bool 的零值,于是「不是图片」这个答案恰好从 JSON 里消失了。页面把这份沉默读成了图片——判断写的是image === false,而undefined不是false——于是在一个 .md 上画了一张标着「图片」的空缩略图。 - 窗口背后的壁纸看不见。三条背景规则是无条件的,而侧轨 + 面板 + 右栏正好铺满窗口,图片被封在下面。两条专为它写的规则因此一次都没生效过。面板让开之后它们终于显形,而它们做的事并不是想要的:侧轨降到一层薄霜,空页光晕不再从
--surface取色(深色下那是一团黑雾),正文自带阴影而不是在图片上切出一块板子。顺带:侧轨 54px 的命中区盖住了正文右缘,任何往右排的控件(回退入口就是一个)都会丢掉右半边。 - 关掉的度量栏下次启动又开着。没有任何地方把这个选择写下来。而且即使在同一次会话里,把窗口收窄再拉宽,也会重新打开一个读者已经关掉的栏——折叠助手把宽窗口下的值存在一个初值为
true的 ref 里。现在只有「读者主动关闭」会被记下来;因为窗口不够宽而折叠,不动宽窗口下的选择。 - 委派出去的运行自问自答。表现为 Studio 从不弹出提问卡,模型反复回答「ask 无交互响应(fallback)」并让你去修——它读的是自己的工具结果。子代理的提问找不到提问者,返回了为自主运行写的那句兜底文案。根执行器有提问者(
EnableInteractiveApproval把控制器接了进去),子代理从来没有。现在从调用上下文继承:被委派的运行有一个正阻塞在它上面的父级和一个等着的人;fleet 条目和并行任务刻意丢掉提问者,因为多个之中某一个提的问题没有读者知道是谁在问;后台任务跑在根本没有调用的上下文里。三种情况本来就在关键处不同,不需要额外的开关。 - 远端拒绝被报成「这次请求没能送到内核」。请求到了,内核也长篇回答了,两层把这个回答扔掉了。传输失败和「远端内核明确拒绝」是两个不同的问题、两条不同的下一步,只有编码能承载这个区别——现在分别是
remote.unreachable和remote.kernel_refused,后者带上主机名和它实际说的话。另一半是 hub 端口只认 JSON、其余一概丢弃,于是每一条纯文本回答到窗口都只剩状态码和路径。 - MCP 服务器全部显示「未连接」。十二个启用的服务器,每个都列着自己带来的工具,每个都写着未连接并配一个「重连」按钮。什么都没坏——配置里的 MCP 本来就是目录优先:启动时注册缓存的工具集作占位、不起进程,第一次真实调用才握手。现在由目录而不是宿主来回答:一个服务器的工具在本会话注册表里,它此刻就能被调用,不管它的进程在做什么。面板对这种情况说「待命 · 首次调用时启动」,并提供「立即连接」而不是「重连」——没有东西失败过,也就没有东西在重试。
- 升级后存储位置被重置回 C:,而原来的位置再也选不回来。两个缺陷,后一个才是把人困住的那个。重置来自安装器:
studio.nsi请求管理员权限,完成页又由它自己启动 Studio,于是应用继承了安装器的令牌;在用别人凭据提权的账户上,%APPDATA%因此解析到那个管理员的配置文件。现在改由explorer.exe启动。困住人的是「搬迁只记录在一处」:目录现在自己说明身份——搬迁在拷贝被验证之后、配置被告知之前写下.reasonix-root.json。目标已经装着本根自己的数据时,预检规划成「接管」而不是拒绝。判定靠结构而不是相似:要么有标记文件指名这个根,要么该根声明了自己拥有哪些条目且文件夹里只有这些。独占且无标记的文件夹无法与陌生人的文件夹区分,因此拒绝而不是猜。 - bash 对拖进来的外部文件说「No such file or directory」。从工作区外拖入一个文件夹会铸一个令牌,注册给读工具的解析器——映射到真实目录的地方在那儿,而且这个授权是只读的,把真实路径交给 bash 就等于开了一条可写的进去的路。所以令牌不是路径,bash 对它的回答就是 shell 自己的那句。同一轮里拿到令牌的模型会信这句话:它对令牌跑
ls,再对整个主目录跑find,得出「这个引用是虚拟的、文件不存在」的结论——而文件一直躺在桌面上,read_file从头到尾都读得到。bash 现在在执行前认出令牌,说明它是什么、哪些工具能解析它。是「认出」而不是「猜某个词可能是什么意思」:去问解析器,它的键是宿主铸的。
隐私
- 可选遥测不再携带安装 id。这个匿名 id 此前随指标一起上报,为的是仪表盘能按信号显示去重后的日活。留着这个答案就意味着留着「每个安装 × 每个信号 × 每天」一行——约 2800 万行——而其上的 30 天
COUNT(DISTINCT install_id)是这个数据库全部的读取账单:主键以date打头,每次查询只能裁掉窗口、其余全表扫描,八个信号每小时一轮,一个仪表盘模块一天约 54 亿行读取。客户端不再发送这个 id,服务端不再写也不再创建这些表,为了让那条查询活下来才存在的每小时 rollup 一并撤掉。聚合表保留同样的信号,以事件计数的形式、总共约 18 万行。
macOS 已用 Developer ID 签名并公证,打开时不需要清除隔离属性。Windows 包未签名 —— Authenticode 签名绑定在受保护的 main-v2 上,本分支拿不到它,所以 SmartScreen 会告警:选「更多信息」,再选「仍要运行」。Linux 从 .deb 安装。
三个平台都能自更新:Linux 走自己的包,Windows 运行下一个安装器,macOS 替换自身 bundle。