Skip to content

v0.1.12

Choose a tag to compare

@github-actions github-actions released this 02 Jul 17:15

更新日志

紧随 v0.1.11 的第二轮全面加固:换一批新眼睛对全库再审一遍(上下文核心 / 服务层 / 工具层 / Web / 提示词与 harness 设计),加一轮真实浏览器的全视图视觉评审(明暗主题 × 桌面/手机 × 全部六个页面)。找到的 19 个问题全部修复,并由独立的对抗复核确认无一误修。1433 项后端 + 243 项前端测试全绿。

修复(稳定性 / 安全)

  • 状态轮询不再可能崩掉进行中的回合:右侧面板的上下文用量显示会高频调用 token_count(),它的 token 备忘录写入与工作线程 trim() 的字典遍历同处一份数据——特定时机下抛 RuntimeError: dictionary changed size during iteration,直接砸断正在流式输出的回合。备忘录现在有了自己的锁,正常聊天 + 状态轮询的组合彻底安全。(73e5c27)
  • 密钥环写入原子化desktop.json 存着你所有 provider 的 API key,过去是就地截断重写——写到一半崩溃/断电会清空全部密钥;两个并发的保存操作还会互相丢失对方的条目。现在走临时文件 + 原子替换(0600 权限),所有读改写(含旧版 key 迁移路径)在一把锁下串行。
  • 断线重连不再丢帧:角色正在输出时恰好重连,重放窗口内新产生的帧过去既不在重放快照里、也不会实时下发——永久静默丢失。重放现在循环追平后才切换到实时流。
  • Linux bwrap 沙盒下 terminal(workdir=…) 生效了:过去 jail 参数硬编码切到工作区根目录,模型指定的子目录被静默忽略(npm install 跑错地方却毫无提示)。macOS 与 Landlock 一直是对的,现在三层一致。
  • 搜索在沙盒被拒时如实报错:过去会静默退化到不经沙盒的纯 Python 文件读取;现在与 terminal 一致——沙盒不可用就明确拒绝,绝不静默降级。

修复(提示词 / harness 设计)

  • execute_code 不再宣传已下架的联网工具:它的模型可见文档还在教 web_search/web_extract,但这两个工具早已搁置——模型照着写脚本必然撞墙白烧一回合。文档与真实能力对齐;顺带清掉了沙盒暂存目录里最后一处旧名残留。
  • terminal 超时文案与真实行为对齐:超过 600 秒的前台超时实际是截断(附提示),不是文档声称的"拒绝"。
  • 每回合尾部瘦身:volatile tail 过去每回合重发两句永远不变的工作区介绍(缓存前缀里已有一份)——现在只发真正动态的事实(隔离/网络/日期),长会话省下可观的重复 token。

修复(Web)

  • 会话切换的竞态关死:刚销毁的会话的迟到帧过去可能写进下一个会话的消息流;四个即时回调补上了销毁守卫。
  • 连接建立前发消息不再报错:先前会弹一条生硬的 "not connected"——现在自动进入持久发送队列,连上即按序送出(气泡即时出现,符合"每次点击立即响应"的原则)。
  • 聊天设置的粘性开关(个人网站 / 演员模式 / 沙盒)在快照或角色变化时正确回收,不再显示上一个角色的残留状态。
  • Gateways 空状态居中重排,去掉重复按钮。

其余

窄窗口切换后立即裁剪上下文(而非等到下一条消息);请求日志遇到单条超限记录不再自清空;hub 超时的操作会真正取消而非孤儿化;世界书关键词扫描少做一遍全文小写化;现场审计方法论沉淀进 docs/AGENT-FIELD-NOTES.md(含一个会伪装成主题 bug 的无头浏览器渲染伪影)。


Changelog

The second full-sweep hardening, right after v0.1.11: a fresh five-track audit (context core / server / tools / web / prompt & harness design) plus a real-browser visual review of every view × theme × viewport. All 19 findings fixed and independently re-verified by an adversarial review. 1433 backend + 243 frontend tests green.

Fixes (stability / security)

  • Status polling can no longer crash an in-flight turn: the side panel's context-usage display calls token_count() frequently; its token memo writes raced the worker thread's trim() dict iteration — under the right timing, RuntimeError: dictionary changed size during iteration killed the streaming turn. The memo now has its own lock; chatting with the panel open is fully safe. (73e5c27)
  • The keyring is written atomically: desktop.json holds every provider API key and used to be truncate-rewritten in place — a crash mid-write wiped all keys, and two concurrent saves could silently drop each other's entries. Now temp-file + atomic replace (0600), with every read-modify-write (including the legacy-key migration) serialized under one lock.
  • Reconnect no longer loses frames: reconnecting while the character is mid-stream could permanently drop frames produced during the replay window (in neither the snapshot nor the live feed). The replay now loops until caught up before switching live.
  • terminal(workdir=…) works under the Linux bwrap jail: the jail argv hardcoded a chdir to the workspace root, silently ignoring the requested subdirectory (npm install ran in the wrong place with no hint). macOS and Landlock were already correct; all three tiers now agree.
  • Search fails honestly when the jail is refused: it used to silently degrade to unjailed pure-Python file reads; it now refuses with a visible error, same as the terminal — the isolation ladder never degrades silently.

Fixes (prompt / harness design)

  • execute_code no longer advertises the shelved web tools: its model-facing docs still taught web_search/web_extract, which are deliberately disabled — the model would write a script straight into a dead end. Docs now match real capability; the last legacy-named staging file is gone too.
  • terminal timeout wording matches behavior: an over-limit foreground timeout is clamped (with a note), not "rejected" as the schema claimed.
  • Slimmer per-turn tail: the volatile tail re-sent two never-changing sentences about the workspace every turn (already taught once in the cached prefix) — it now carries only the dynamic facts (isolation/network/date), saving real tokens over long sessions.

Fixes (web)

  • Session-switch races closed: a just-disposed session's late frames could write into the next session's message stream; all four immediate callbacks gained the disposal guard.
  • Sending before the connection is ready no longer errors: instead of a raw "not connected", the message rides the persisted send queue and delivers once attached (the bubble appears instantly, per the instant-response principle).
  • Sticky chat-settings toggles (personal website / actor mode / sandbox) reconcile on snapshot/character changes instead of showing a previous character's leftovers.
  • Gateways empty state centered, duplicate button removed.

Everything else

The context trims immediately after a narrow-window model swap (not at the next message); the request log never self-empties on a single oversized record; timed-out hub operations are cancelled rather than orphaned; the world-book keyword scan lowercases the scan text once instead of per entry; the field-audit methodology (including a headless-browser rendering artifact that mimics a dark-theme bug) is recorded in docs/AGENT-FIELD-NOTES.md.