Repository navigation
znaide v1.0.4
znaide v1.0.4(2026-09-10)
两条线:轮次不再被硬砍(可配 + 撞上限可续跑 + 打转刹车),配置语义修订(多 provider 真正可切换)。
一、轮次预算:从"硬砍 40 轮"到"可配 + 续跑 + 刹车"
旧实现是 max_turns: 40 硬编码、撞上限即停——不总结、不续跑,长任务直接被腰斩,且没有任何配置入口。
1. 上限可配、默认抬高 —— DEFAULT_MAX_TURNS 40 → 200;新增 --max-turns <N> 与 config 的 max_turns(0 = 不限)。优先级:命令行 > config > 200。0 在引擎里映射为无限预算。
2. 撞上限不再丢任务 —— 新增 SessionEvent::RoundsExhausted,交互模式弹"继续执行"确认框(y 再放一批 / n·Esc 停在当前进度);无头模式在结果里说明"已达 N 轮"以及怎么调大(--max-turns N,0 = 不限),不再只丢一句"任务没干完就停了"。
3. "原地打转"刹车(替代靠轮数硬砍) —— 以 (工具名, 原始参数) 完全相同为签名计数:重复到 3 次在工具结果尾部插一句提醒,劝模型换方法(给一次自救机会);重复到 6 次判定"原地打转",中止本轮并点名工具与次数。换参数不触发计数,所以"挨个读 30 个文件"这类正常长任务不会被误杀。
4. 状态栏显示轮次 —— 底部状态栏新增 轮 本轮已用/上限(不限时显示 ∞),数据由引擎每轮发的 SessionEvent::RoundStarted { used, limit } 驱动,不靠 UI 估算;/config 改完上限立即反映。
二、配置面板:轮数上限成为独立一步,并带出当前配置
- 配置向导由 4 步变 5 步:
1 服务商 → 2 模型 → 3 API Key → 4 轮数上限 → 5 验证。第 4 步直接敲数字即可改(0= 不限,留空 = 默认 200),Enter/s验证;第 3 步按Enter进入该步(老习惯直接按s仍可跳过)。 - 重开
/config带出当前已配置的值:服务商/模型/端点/Key/轮数上限,并在顶部显示"当前配置"摘要行;服务商列表游标落在当前那个上;模型列表自动选中当前模型;查询失败转手输时预填当前模型名。 - 两个细节:走
api_key_env的 Key 不会被预填成明文(否则保存会把 Key 落进配置文件),界面标注"来自环境变量,留空即保持";重选同一个服务商不再清空已配的 Key。
三、配置语义修订(v2):多 provider 真正可切换
旧语义有个自相矛盾的死结:顶层 model/base_url 覆盖预设,而 api_key 反过来由预设优先;并且面板每次保存都写顶层三件套——于是用过一次面板后,顶层永久遮蔽所有预设,改 provider 只换 Key 不换端点/模型。
- 面板保存改写进 provider 条目 ——
save()把 model/base_url/api_key 写进providers[当前服务商],不再写顶层三件套,并清空顶层。此后改"provider": "xxx"(或--provider xxx)= 换整套(端点 + 模型 + Key)。 - 三个字段口径统一 ——
model/base_url/api_key一律"顶层 > 预设",不再出现"新 Key 配老端点"的错配。优先级:CLI > 环境变量 > 顶层(手动覆盖)> provider 条目。 context_window下沉到 provider —— 各服务商可各配各的窗口(内置表仍作最后兜底);在 40k 的 ollama 与 1M 的云端模型之间切换时,ctx 占用条不再算错。- 预设按字段合并 —— 内置预设做底,你在
providers里只写要改的字段即可,不再因为写了base_url就顺手丢掉内置的model/api_key_env。 - 老配置自动迁移 —— 启动时把顶层
model/base_url/api_key/context_window搬进当前 provider 条目并清空顶层(一次性自愈,控制台提示"检测到配置由其他版本写入,格式标记已升级")。迁移前后生效配置完全一致,有单测与真配置干跑双重验证。
顶层三件套仍可用作手动临时覆盖(优先级高于预设),只是面板不会再写它们。
验证
cargo test --workspace:core 100 / mock-e2e 17 / tui 80,全绿。- 新增覆盖:轮上限用尽的无头提示、
max_turns=0真不限(连跑 9 轮不被截断)、重复相同调用被中止(≤6 次)、RoundStarted逐轮上报(used, limit)、config 的字段级合并 / provider 窗口优先 / 保存写进条目 / 迁移前后生效一致 /max_turns落盘往返。 - 真配置干跑:迁移后顶层清空、值进
providers.deepseek,启动解析出的模型不变。 cargo build --release通过,--version输出 1.0.4。
兼容性提示
- 老配置会被自动迁移一次(会改写
config.json,建议先备份)。 - 顶层
context_window现在只作兜底:建议把它挪进对应的 provider 条目(迁移会自动做)。 - 之前依赖"预设 Key 盖过顶层 Key"的行为已统一为顶层优先(仅影响同时手写了两处 Key 的配置)。
发布后补入的修复(同一版本号替换)
以下几处在 1.0.4 首次发布后随即修复,随本版本资产一并替换(未升版本号):
- 配置面板输入框支持粘贴 —— 此前向导一打开,粘贴就被整段丢弃,长 API Key / 端点只能手敲。现在文本输入态(API Key / 端点 / 模型名 / 轮数上限)可直接粘贴:只填入、不提交(回车才算),换行会被丢掉(单行输入);权限确认与破坏性确认弹窗(
y/n)仍不接收粘贴。 - 修掉"切回旧服务商时,面板里还是另一家的模型/Key" —— 切服务商时只更新了名字与端点,
model仍沿用上一家的,api_key又只查环境变量而不读该条目的明文(面板保存的 Key 就存在条目里),于是切过去 Key 显示未设置、验证必然失败。现在切换会带出目标服务商自己的模型与 Key(Key 顺序:该条目明文 > 该条目的api_key_env环境变量 > 空);模型列表里没有当前模型时置顶保留并选中,避免"只是切回这家、回车一下模型被换成列表第一项"。另外 Key 来自环境变量时保存不会写成明文,手输明文后该标记自动清除。 - 修掉 ctx 占用条把模型窗口算错(误报"快满了"、劝人做没必要的压缩) —— 分子没错(最近一次请求的真实
prompt_tokens),错在分母:窗口靠模型名查内置表,认不出就回默认 32768,而deepseek-flash(不含deepseek-v4)、qwen3.8-max(被 ollama 的qwen3兜底吞成 40960)这类真实模型 ID 都命中不了 → 占用条成倍虚高、变红,并弹出⚠ 上下文已用约 N%,可以 /compact的提示。压缩是真的会切历史的,这条误报比显示不准更严重。现在:- 内置表查不到就按"未知"处理(不再拿默认值假装知道):状态栏显示
ctx ~21.4k 窗口未知,只报真实绝对量、不给百分比、不触发 90% 压缩提示,也就不会劝你做没必要的压缩; - 表内补齐真实 ID:
deepseek-flash/deepseek-pro归入 deepseek v4 代(1M);新增云端qwen3-max/qwen3.8-max档,不再被本地qwen3的 40k 规则吞掉; /config向导新增第 4 步「上下文窗口」(5 步 → 6 步):直接填数字即固定该窗口,留空 = 按模型名自动;模型不在表里时,这里是唯一能把它填准的地方。窗口与轮数一样按服务商各记各的(切服务商带出那家自己的值、保存写进该 provider 条目),重开面板会带出当前已配的窗口。- 涉及面:
model_context_window()/Resolved::effective_context_window()返回Option,Config::save()增加context_window参数(写进 provider 条目,None/0= 清除固定值)。README.md/README.en.md/docs/使用说明.md同步删掉"未命中默认 32k"的旧口径说明。
- 内置表查不到就按"未知"处理(不再拿默认值假装知道):状态栏显示