github esengine/DeepSeek-Reasonix studio-v2.16.0
Reasonix Studio v2.16.0

pre-release2 hours ago

本版的主线是让屏幕上写着的东西与内核里的事实是同一件:任务面板读内核发布的那份清单而不再从转录里把它猜回来,一次被拒的工具调用带着主机给它的身份而不是一句话,卡片名出内核真正跑的那个能力,能力清单在调用被花掉之前就说出它要的参数。工作台补上四件它做不到的事——会话内查找、代码块高亮、消息改写重发、能力名到卡片。回合多了一个出口:把清单交回用户,而不是被主机推着往下走。界面一侧是一轮以实测为准的整理(阅读尺寸与栏宽、等宽面、汉字下的小型大写、浅色的灰、卡片的高度成本),以及三个早已失灵的门。自 2.15.0 起 43 个提交。

升级路径:无需人工步骤。三平台照旧自更新——Linux 走 .deb,Windows 运行下一个安装器,macOS 替换自身 bundle。

新增

工作台:四件它做不到的事

  • 会话内查找。转录只挂载几十张卡片,所以浏览器自带的查找只看得见屏幕上那些:200 条消息时 DOM 里有 59 张卡,第一条根本找不到。查找改读行本身——saidBy()Item 是穷尽的,新卡片必须回答它携带什么文本。命中用高亮注册表画,而不是包一层标签:那等于重写 React 拥有的 markdown,而那些卡片在每一个增量上重渲染。
  • 代码块高亮。rehype-highlight 像 katex 一样惰性加载,输出的是 class 而非内联颜色——自己写十六进制的高亮器会离开令牌系统、从此不跟随主题。调色板是四个新令牌,注释与标点走 --faint--muted,跟随对比度档位。没有标注语言的围栏不上色:猜一门语法等于把散文画成代码。
  • 一条消息可以改写后重发。由内核已有的两件事组合而成:把对话回卷到那一回合,然后发送。RewindResult 的 TS 镜像少了 conversationOk,于是"动了文件但对话仍在"与"对话被截断"无从分辨——那会把消息发两次。类型补全,这一对进了 wireparity
  • 调用解析到的能力会到达卡片,仅当名字尚未说出它时:tool:grep 写在 Search 旁边是一件事说两遍,skill:review 不是。

任务清单,与回合的出口

  • 面板画的是清单主人所持的状态GET /todos 一直在发布那份权威清单——最新一次 todo_write 与其后每一次 complete_step 推进的合并——而窗口从来没调用过它。面板自己从转录里解析 todo_write 的参数重建一份,那是 rebuildTodoState 的第二份实现,并在两处漂开:它不重放 complete_step,所以每一次签收都丢了;它不看回执,所以一份被内核拒绝的清单成了计划。每一次重建——挂载、面板重绑、流中断——都把面板重置回"模型最后写下的样子"。已签收的条目渲染成当前项、此后任何调用都推不动它,这就是"待办面板清不掉"从外面看的样子。
  • 任务清单根本不可能从转录导出:推进不是 todo_write 调用,而被拒绝的写入是。所以 fromHistory 不再尝试,窗口去问;回合结束再读一次,因为有些移动没有事件可说(一次取消会让内核重建自己的状态);读取失败时面板保持原样而不是清空。
  • 投影在状态移动时就欠下,而不只是 id 变了的时候withTodoIdentityTail 只要每个步骤 id 还能在视图里读到就认为不欠——而 id 永远读得到,它们就在模型自己的 todo_write 参数里。底下的状态不会留在原地:complete_step 在主机侧推进那份权威清单而模型什么也没写。于是一份主机已经翻过页的清单还按模型最后写下的样子读着,下一次签收点的是主机已不认为是当前的那一项——complete_step 拒绝它,代价是满上下文下的一整轮,且学不到任何关于任务的东西。23 个录制会话里 complete_step 在 43 次调用中失败 16 次,这一类是其中最大的一组。
  • 一个回合可以把清单交回用户,而不是被驱动。带着未完项停下来此前一律读作"活没干完",continueUntilReady 会拿主机写的一句话把它推上至多八轮。对模型能独自推进的步骤这是对的;对下一步输入在用户手上的步骤是错的——呈现一项并等待回复,与提前退出无从分辨,于是一份每回合走一项的清单根本没法走:回合停下、主机重启它、整张清单在一轮里全吐出来。 await_user 成为除 askconclude_blocked 之外第三种由模型决定的收尾,它点名等待中的那一项和用户需要提供什么,清单原样保留,就绪判定豁免未完项,续跑循环不运行。守卫是结构性的:必须有一份未完清单、step_id 必须点中其上未完成的一项、必须有可交互的用户——无头运行拒绝它并被指向 conclude_blocked

工具表面与能力

  • 一个工具在 schema 里,就是此刻可调用的。此前存在三种状态而模型只分得清两种:在 schema 里且可调用、注册了但藏在 use_capability 后面、以及在 schema 里却会被拒——最后一种不是任何人的本意。update_goal 就住在第三种里:534 个真实会话中它被调用 121 次,拒绝 116 次。
  • 把工具钉住不动的那条理由被量掉了benchmarks/tool-surface-cache)。"改 schema 会把缓存前缀搅浑"对任何位置的改动为真、对末尾的追加为假,而没有任何东西测过哪一条适用。实测:同一个工具在头部要 896 个缓存 token,在中部 384,追加在尾部不花任何东西;一个尾部工具在"有/无"之间来回三次,缓存读数稳定在 1920 与 2048 之间、没有一次未命中尖峰——因为缺席的那份表面是在场那份的字节前缀,一条缓存同时服务两者。于是 ProviderSchemas 分两段排序:稳定工具在前,本回合准入的上下文工具在后。
  • 能力清单说出一次调用要被held到的参数。藏在 schema 之外的能力靠列目录再按 id 调用来够到,而清单只有 id 没有参数,第一次调用只能是猜。534 个会话里 12 次调用对 3 次 inspect,5 次带回"它需要……"。契约错误在调用被花掉之后才打印的两张表,现在在调用之前就在清单里:必填字段名,和每一个声明过的属性。从目标自己的 schema 经注册表读出——不是注册表工具、或 schema 没声明属性的条目什么也不说,而不是报一张空表让读者当成"它不要参数"。
  • 卡片名出内核真正跑的那个东西。内核注册的 54 个工具里有 22 个在两张表里都没有条目,于是一次经 use_capability 的调用渲染成它自己 title-case 过的 id,顶着那个"折角的纸"标记。一次委派、一次记忆写入、一次安装全都读作文件读取,而类别颜色——那一行唯一的警示——是中性的那个。install_source 是其中最糟的一个:它不是只读的,它安装一个 MCP 服务器,而它根本没有身份。兜底标记改为中性圆点:"·" 是一份文档,一个没有条目的名字此前在声称自己读过文件。
  • 重新打开的转录说得出代理够到的是哪个能力。实时转录读作 "Remember · 2026-08-20 会下雨",重开后读作 "MCP" 且没有参数——身份在三处被丢掉。现在 historyToolCall 加入 mirroredWireTypes:它此前是一对手写的类型、没有守卫,那正是一个字段在一侧消失而无人察觉的方式。

主机归因

  • 一次被拒的工具结果带着主机给它的身份。这棵树的规则是"调用者必须分辨的错误携带身份、而不是一句话",工具结果是那个例外。按天在真实会话上量过:shell 那一侧 08-17 就收口了、此后每一次失败都写下了身份;其余从来没有——08-16 有 27 次、08-17 有 10 次、08-25 有 16 次,九月仍在到达。ToolFailure 现在携带它:非空即是"失败"这个事实,RefusalCode 点名主机的拒绝。这个身份此前也从未过线——event.Tool 一直有 RefusalCodeeventwire.Tool 没有,所以没有任何前端读得到;双方同样缺失,所以 parity 是静默的。现在失败标签说出那是哪一种拒绝,而不是"失败"。
  • token 估算量的是真正发出去的那个请求。把 provider 表面收窄到"本回合准入的"之后,估算被落下了:context_breakdownestimatedVisibleRequestTokens 都向注册表要 Schemas(),那会连本回合没带的工具一起答。而估算要与 provider 强制的窗口、与主机折叠用的那条维护线相比——一个把没带的工具也数进去的估算,会比对话需要的更早折叠。
  • 被别处持有的会话说得出是哪个进程。删除另一个 Reasonix 进程打开着的会话会被拒绝,而那个拒绝是条死路:面板映射属于一个进程,所以侧栏看不到可关闭的面板、任何窗口里的任何按钮都关不掉它,而 session.in_use 渲染成"被别处持有——请先在那里关闭"却说不出那个"别处"是谁。守卫为了拒绝本来就读过租约,pid、主机名和取得时间它全都知道,全部在边界上丢掉了。session.in_use_by 携带持有者,且仅当持有者是另一个进程时——本进程持有的租约确实意味着这里有写入在途,那是另一回事。实测于共享同一状态根的两个宿主:拒绝点名 pid 88240,pgrep 确认那是第二个宿主,它消失后删除成功。

计量:串行化写入者到底花掉了什么

  • 工作区写入租约是两个会话不能同时写一个项目的原因,而这件事花掉了谁多少,此前没有数字。唯一的记录是屏幕上一句"等了 2.3 秒",且只对超出一秒宽限期的等待出现——把常见情形整个藏住了。workspacelease.Stats 为每一次持有结账:含宽限期内的争用次数、其中多少成了通知、总等待、持有时长,以及持有中有多少发生在最后一次写入请求之后。最后这个数字是"在最后一次验证处就释放"这条提案成立与否的全部依据,而此前没有任何东西在量它。它骑在一个影子事件上,TodoProgress 已经在用的那个形状:没有门读它,没有一个 prompt 字节随它移动。写这个测试时发现一个真实的顺序错误——取得租约的那次请求,其时间戳早于它所等来的那次取得,于是 idle 量出来比它所属的 held 还长。
  • 一个工具把这些账从会话日志里读回来,并拒绝让任何数字表示它并不表示的东西:分母是"持有次数",所以一个写了但从未等待的会话要计进去——那是这个比率的大部分;争用与"成了通知"是两列;零长度的持有没有 idle 占比,而不是占比为零;被大小上限截断过的日志让每个数字成为下界,这句话写在渲染里而不是留给读者去记得。
  • 上报走已有同意的那条通道:三个封闭枚举加进上传白名单,仪表盘上与其他设置指标并排一组。策略没有变,仍然拒绝非发布构建、CI、DO_NOT_TRACK,以及 auto 档下任何非交互会话。

排版与配色:一轮以实测为准

  • 答案设在可读的字号上、可读的栏宽里。两个只有一起才有意义的数字:转录正文此前是 820px 栏里的 13.5px,每行 103 个拉丁字符或 56 个汉字——比"眼睛还能不用找就落到下一行开头"的 45–75 / 30–40 多出一半。--read 到 15px(中文 16,笔画更密),--doc 到 706px——后者不是口味:这一栏必须容下的最窄的东西是 80 列 IBM Plex Mono,实测 624px,转录自己的缩进与内边距还要 82px。实测 1600x1000:103 → 71 个拉丁字符,56 → 39 个汉字。
  • 答案读起来是答案,右栏有地方可落眼。转录此前只靠颜色和行距区分"模型说的"与"工具做的"——同样 14.5px、同样字重——于是一列下来扫描成一条没有分节的事件流。答案拿到一级字号,机器输出留在原处,节奏因此分成三档真实的台阶:两行机器输出之间 22px,跨过边界进入话语 32px,两段独立发言之间 42px(原为 22/28/34,方向对而台阶太浅)。每张工具卡片都带一个填充的图标片,于是填充什么也没说;中性的那些现在透明,net/write/ask/deleg/mcp 保留填充,填充就变成了它的注释一直声称的那个信号。
  • 等宽字面还给机器。等宽说的是"这是机器产生的":路径、命令、id、不能跳动的数字列、必须占住格子的标记。而窗口在用它排自己的句子——每一个空状态、每一条设置脚注——一列这样的散文读起来像终端而不像被写下来的东西。判断是结构性的、从不看词:一个 class 是等宽的,当且仅当 app.css 里有规则给它 var(--mono);一个元素渲染散文,当且仅当它自己的子节点调用 t()。两者一起在 155 个里找出 63 个,那是截图做不到的——扫描只看得见这一次渲染画出来的东西。等宽字符占比 42% → 33%,转录内 54% → 45%,右栏 37% → 22%。
  • 小型大写排版不再施加于汉字。带字距的大写是拉丁字母的做法:字距在那里分开单词,在汉字上它拉开的是单个字形的笔画,而大写根本无从作用。样式表本来就知道(一条 :lang(zh) 规则给 17 个小型大写选择器换了常规字面),但此后又写了 10 个,其中一个是工作台唯一的语义标题。哪些属于这一类由"文本从哪来"settle,绝不靠读文本:.hl .fail 渲染"{n} 项失败"因而加入,.hl .src.hl .who 就在同一行徽章里却留下——它们渲染的是 MCP 服务器名和子代理 id。
  • 中文里的块标题不再低于它所引介的东西。右栏有四级,而块标题在所有四级之下:12px w700 的 --ghost,对着 13px --faint 的行、--muted 的图例、--text 的数值。在英文里那条带字距的大写撑得住它——那正是 eyebrow 的定义;中文没有小型大写可撑,字距一去就只剩一行略粗略淡、与下面各行等长的字。
  • 浅色方案的灰是暖的。浅色中性色此前沿 255 号色相排布,#EEF1F7 里蓝多于红——那是工程工具的样子——而它坐在琥珀色强调色之下,两者在色轮的对侧:窗口里最大的那块面与"这里需要你"的颜色在悄悄互相抵消。现在沿 85 号色相,#F4F1EA只有色相与彩度移动:52 条声明的明度一条未动,所以没有任何对比度为此被交易掉。深色保留它的蓝。

卡片的成本

  • 一行输出不该花掉 109px。一次结算完毕、整个输出就是 "ok" 的调用量出 109px,对着什么都没打印的 39px——两个字符换来 2.8 倍高度。九次普通调用就填满一屏,其中三分之二是什么都不装的留白。三笔成本各自量过:块自身的内边距与底色(一行输出两样都不要)、画在每张结算卡片上而不管有没有被裁的"下面还有"渐隐(裁剪逻辑本来就知道,现在它说出来)、以及 .term 那 13px 下边距。九次普通调用的一回合:1474px → 1162px。
  • 一行说出它运行的是什么,并且只说一遍。shell 行显示命令的前 96 个字符,对 PATH=$(echo $PATH | …) go test ./x 来说那是六十个字符的管道装配、一个动词都没有。命令的哪一段命名了它运行的东西只有解析器答得出——对文本跑正则正是这棵树不做的词匹配——所以内核来答:shellrun.OperativeCommand 按解析出的命令自己的字节偏移按位置切掉前导赋值,引号与替换原样存活。它骑 ShellExecution.Subject,从不取代命令:授权界面拿到的是全文,行的 title 也是。
  • 横向跑出去的输出会说自己跑出去了。纵向被裁的输出有两个提示(脚部的渐隐、"显示全部"),横向藏起来的一个都没有,而滚动条是覆盖式的:静止时那一行看上去就是完整的。实测 499 个真实会话、7587 段工具输出:54% 的最长行超出这个宽度能容的约 80 列,31.5% 超出 120 列;一个屏上会话里有 19 块横向滚动,最糟的一块在 624px 的盒子里装着 2881px 内容——78% 在屏外而没有任何东西说。

修复

  • 回合结束时的回执卡片此前不可达。它藏在一个没有任何控件写过的 localStorage 键后面,所以它不是"默认关",它是根本打不开。它报告的是这一回合改了什么、验证了什么、什么没被验证——正是读者在回合停下时想要的东西。现在它默认开,关掉它的开关也存在了,与其他"本机显示"选项并列。
  • 查找命中落在查找栏之外。那条栏浮在转录上沿,所以按通常 12px 净空落位的行就落在它底下——一次搜索的第一条命中正是读不到的那一条。
  • 每个面板的转录有自己的 idid="flowScroll" 写在 Transcript 里,而它每个面板渲染一次,于是两个打开的面板应答同一个 id,右轨的 aria-controls 指向先来的那个——未必是它所滚动的那个。
  • MCP 步骤底下那条线说出它的标记所说的。装订线用两处命名类别:标记带色相,其下的线带同一色相的 30%。net、deleg、write、ask 各有两半,mcp 只有标记——它的线落到默认灰,于是图标说"这出网了"、底下的条纹说"普通工具"。src/styles/gutter.test.ts 把两半都从 app.css 里读出来。
  • 侧栏不再数没有的东西。右轨渲染十二个计数,其中六个说"0 会话"。机器行数的是打开的面板,所以每台机器静止时都这么说;一个没有存档对话的工作区在自己名字底下这么说,而它下面没有行本来就已经说过了。
  • 没人在看的面板停止轮询、停止重绘。每个会话保持挂载、屏外的用 CSS 隐藏,所以切标签不丢流、不丢转录、不丢滚动位置。这笔交易只在隐藏的面板确实安静时才划算,而其中一个不是:/status 轮询的门是"回合在跑",不是"面板可见"。于是每个带活跃回合的后台面板每秒要花四次往返、四次整棵子树重渲染,账单随打开的对话数增长而不是随正在看的那一个。实测(mock port + 假定时器):每个隐藏的运行中面板此前每秒 4 次 /status 读取,此后 0 次。

门禁与工具

  • 六个浏览器守卫早已不再解析"[data-pane="flow"]" 关掉了它自己的字符串,从 60b0288 起 cards、bench、look、motion、scale、verify 一个都没解析过——21 条卡片几何断言、20 条行为断言,没有人跑过。而 selfcheck 把这读成健康:它注入一条假断言、问退出码是否变红,而 SyntaxError 也是非零。它现在先问守卫解析不解析,再问它能不能失败。
  • 对比度扫描读的是被画出来的那个颜色。扫描此前手工解析 getComputedStyle 的文本,而计算后的颜色按它被写下时的记法返回:oklch(0.85 0.012 255) 被当成 8 位 RGB 读成 r=1, g=0, b=255,就是报告里满屏的 #0100FF;色相 262 给出 b=262、打印成七位宽的 #0100106于是每一个设置页都在被拿去和屏幕上并不存在的颜色比对:深色里十行"低于 AA"、浅色里八行是凭空造出来的,而其中真有一条失败也分辨不出来。现在它画而不是解析:把值填进 1×1 画布再把像素读回来,那是画出被测物的同一个引擎。两个方案现在在十二个区段上都报零。
  • 一个开放的原因说得出承载它的是哪个 effectPROJECTION_CAUSE_WITHOUT_SOURCE 停在 17:开放性由组件拥有的每一个 effect 共同判定,而来源是从 d.by——被展示的那一行所命名的单个 effect——读出来的。Transcript 有十二个:让 unmountOpen 为真的是 456 行那个清理函数读不出来的 effect,而 by 指向 325,第一个 setup 开放、根本没有清理函数的那个。谓词现在只声明一次、判定与归因都读它。
  • trace fixture 记录的是形状,不是一次测量。它们门着桌面 reducer 被拿去比对的东西,所以 stabilize() 剥掉一切属于测量而非回合结构的字段——工具调用的 DurationMs 一直在那里被清零。租约账目带着 heldMs/idleMs 到达而没有任何东西剥它们,于是文件记下了某一次运行恰好持有了多久:写下时 24ms,下一台跑它的机器上 23ms。这个测试不可能连过两次,它在 ubuntu、macos、windows、race 与 coverage 上同时变红。
  • 样式表不带任何注释。668 个注释块、1500 行,在读规则时一次一段地遇到。它们几乎没有一条在复述 CSS:它们是量过的颜色、布局机制、以及为什么显而易见的那条规则是错的——比它们所在的位置更值钱的知识。它移进两份从头读到尾的伴随文档:TOKENS.md 持有词汇表的法律,LAYOUT.md 逐条跟着 app.css没有任何一条声明移动过。
  • 注释规则说出它指的是哪种语气、由谁持有。"绝不写:事故或对话历史"是一条没有人认为自己违反过的规则:手里有修复的人叙述这个修复,而结果通过所有现存的门——篇幅规则比的是行数,没有任何东西读语气。规则现在说出它的判据(一个从没见过早先版本的读者不该损失任何东西,而"关于这段代码自身行为的过去时"就是那个破绽),给出成对的例子,说出叙述该去哪里,并说明它压过周围的风格。它也说明没有门读语气、而且不会建一个:把叙述和约束陈述分开需要一张短语表,那是这个仓库唯一不建的东西。那条规则由 review 持有,说出来比暗示一个检查存在要好。

macOS 已用 Developer ID 签名并公证,打开时不需要清除隔离属性。Windows 包未签名,SmartScreen 会告警:选「更多信息」,再选「仍要运行」。Linux.deb 安装。

三个平台都能自更新:Linux 走自己的包,Windows 运行下一个安装器,macOS 替换自身 bundle。

Don't miss a new DeepSeek-Reasonix release

NewReleases is sending notifications on new releases.