36 KiB
变更日志
本文件记录 Picobot 各版本的显著变更,遵循 Keep a Changelog 风格。
0.4.0 - 2026-08-13
较 0.3.5 的 3 个 commit 迭代,聚焦 异步子代理 v8 架构、/stop 取消流程 与 前端子代理状态展示 三大方向。异步子代理 v8 为里程碑式架构升级:子代理执行从「父子同步串行」改为「后台异步 + 显式等待」,显著提升多子代理并行吞吐与父代理可控性。
新增功能
异步子代理 v8 架构(父代理不再阻塞)
- 双通道异步通信:子代理结果走独立队列
sub_done_q(直达 wait,不绕 SQLite → bus → reload);用户消息复用现有 bus,channel 适配器零改动。 wait_for_subagents工具(新增src/tools/wait_tool.rs):select!等待子代理完成 / 用户消息 / 超时,支持try_drain批量消费;task tool_result 返回running+ 引导提示,引导 LLM 调用 wait。wait_coordinator(新增src/gateway/wait_coordinator.rs):释放/重获取serial_lock的 in-tool waiting 模式,替代旧的 break-exit 方案;is_waiting持锁后判断,无 TOCTOU。- task 工具异步 spawn 路径(
src/tools/task/runtime.rs+488):CancellationToken注册表 + RAII guard +Semaphore并发限流。 - 子代理完成回调携带
pending_task_ids列表,LLM 据此判断全局进度并决策下一步。 - 崩溃恢复:启动时标记
running -> interrupted,history 加载时对账占位;新增pending_subagents表 + 条件 UPDATE +mark_all_running_as_interrupted。 - 嵌套层级:仅顶层异步,避免复杂度爆炸。
- 新增
docs/ASYNC_SUBAGENT_DESIGN.md设计文档,记录 v8 三个核心不变量、wait 模式、取消机制与崩溃恢复策略。
修复
/stop 取消流程
wait_coordinatorselect!添加 cancel 分支,完整清理状态。ToolContext注入cancel_rx(watch::Receiver clone)。agent_loop工具执行select!对 wait 工具跳过竞速,防止 drop coordinator 清理逻辑。- 子代理完成状态通过
execution_completedmetadata 传播。
前端子代理状态显示与渲染崩溃
MessageBubble:taskStatusConfig补全 running/completed/cancelled/interrupted 状态配色,修复未知状态访问undefined.borderColor导致的白屏崩溃;添加安全回退到 failed 状态。main.tsx:新增ErrorBoundary捕获 React 渲染错误,防止白屏并提供错误详情与恢复入口。useMessages:收到子代理execution_completed事件后,更新主视图中 task tool result 占位消息的 status 字段(running → completed/failed/cancelled),消除永久黄色转圈。protocol.ts:ExecutionCompleted接口新增subagent_status和subagent_summary字段。
测试
src/tools/task/runtime.rs测试模块持续扩充,覆盖异步 spawn / 取消 / 并发限流等核心路径。
0.3.5 - 2026-08-12
较 0.3.4 的 7 个 commit 迭代,聚焦 可观测性、并发性能 与 外部集成健壮性 三大方向。
新增功能
MCP 工具调用超时保护
- 在
McpToolWrapper适配层用tokio::time::timeout包裹call_tool,防止外部 MCP server 挂起导致 agent loop 无限阻塞。 - 超时时间通过
config.mcp_tool_timeout_secs配置(默认 300 秒,0=不超时)。 - 前端 McpTab 设置页提供输入框。
端到端可观测性整改
- trace_id 全链路传播:
BusToolCallEmitter/SubAgentEmitter/processor全链路设置 trace_id。 - AgentEnd 指标配对:补发 5 个 cancel/defensive 路径的 AgentEnd 事件,闭合 AgentStart 指标。
- LLM 计时修正:
attempt_start移入 retry 循环,排除退避等待时间。 /metricsauth:非 loopback 部署时纳入 Bearer token 校验。- recorder 复用:
OnceLock缓存PrometheusHandle,热重启后不再返回 503。 - 结构化日志:新增
tracing_ctx+ JSON 日志格式支持。
修复
压缩期间 session 锁阻塞新建话题
- 压缩任务在 LLM 调用(2-5s)期间持有 session 锁,阻塞
create_session命令获取锁执行switch_topic,导致新建话题后列表刷新延迟。 - 将压缩重构为 4 阶段:
- 短暂持锁:读取 history/compressor/store/session_id/provider_config
- 释放锁:LLM 压缩调用(2-5s)
- 释放锁:DB 写入(store 为 Arc,DB 层自带事务保护)
- 短暂持锁:reload 内存历史
- 并发安全:同 topic 由调用方的 per-topic serial lock 保证串行;不同 topic 完全并行不受影响。
MCP 前端空输入重置为不超时
- 清空输入框时回退到默认值 300 而非 0(0 表示不超时,与用户预期不符)。
- 新增两个 tokio 测试覆盖有超时和无超时(error pass-through)路径。
移除 ChatContainer key remount 修复新建话题列表刷新延迟
- 话题切换时
key={selectedTopic}导致整个ChatContainer子树卸载重建,触发ExpertSelector/ModelSelector重新挂载并发起 3 次冗余 HTTP 请求(getSelectedExpert/listModelOptions/ 模型选择刷新),引入 200-500ms 延迟。 - 改用
topicIdprop 透传话题 ID:App.tsx:移除 key,viewKey纳入selectedTopic保持各话题独立滚动位置。ChatContainer:新增topicIdprop 透传给MessageInput。MessageInput:监听topicId变化清空草稿,替代原 key remount 重置机制。
Panic 安全增强
agent_loop.rs/processor.rs:用catch_unwind隔离工具执行和消息处理的 panic,归一化为错误返回,LLM 可见错误并自我纠正,防止用户消息被静默丢弃。utils.rs:新增panic_payload_message()从 panic payload 中提取可读消息,支持&str/String/ 其他类型降级。bus/message.rs:修复sanitize_incomplete_tool_call_sequences两阶段删除索引未全局排序导致的越界 panic(Phase 1 降序 + Phase 1.5 升序 → 合并后必须重新排序)。
计算器健壮性
- 拒绝
"NaN"/"inf"等非有限输入,防止sort_by中partial_cmp().unwrap()panic。 - 修复阶乘溢出:上限从 170 降至 34(35! 超出
u128::MAX),改用checked_mul替代 unchecked 乘法。 evaluate表达式拒绝非有限结果(如1/0→ inf、0/0→ NaN)。- 新增 7 个 tokio 测试覆盖所有边界场景。
测试
- MCP 超时路径新增 2 个 tokio 单元测试。
0.3.4 - 2026-08-10
较 0.3.3 的 9 个 commit 迭代,聚焦 安全加固、健壮性防御 与 代码质量优化 三大方向。
新增功能
顶栏显示后端版本号
- 复用现有
/health端点返回的CARGO_PKG_VERSION,避免在package.json重复维护版本号。 - 前端挂载时拉取一次,失败则不显示徽标。
文件工具路径限制(最小权限原则)
- 默认行为:文件读写编辑限制在当前工作目录内。
- 新增配置项:
tools.allowed_dirs(白名单目录列表)+tools.file_access_unrestricted(opt-in 全局放开)。 - 共享
resolve_file_path()函数,使用canonicalize()防御符号链接与..路径遍历。 - 前端:设置页 > 工具标签新增"文件访问"卡片,含开关与目录标签编辑器。
- 向后兼容:旧配置默认 cwd 限制(
serde(default))。
安全修复
Shell 会话生命周期管理
GatewayState持有Arc<ShellSessionManager>引用,网关关闭时(ctrl_c和重启两条路径)调用shutdown()。- 新增防御性
Dropimpl,泄露会话时打 warn 日志。 - 子进程 kill 添加 5s 超时,防止无限阻塞。
HTTP 工具 OOM 防护
WebFetchTool/HttpRequestTool实现流式读取响应体(futures_util::StreamExt),防止大响应撑爆内存。- 检查
Content-Length头,分块读取并累计校验大小。 - 默认限制:
WebFetch200KB,HttpRequest4MB。
TimeTool 重复类型转换修复
- 移除
time.rs中重复的u32::try_from调用(复制粘贴错误)。
消除 16 处 unreachable! panic 风险
- 15 个 command handler 文件中
_ => unreachable!()替换为_ => Err(CommandError::new(...)),防止Command枚举新增变体时运行时 panic。
配置占位符校验
- 新增
validate_no_unresolved_placeholders(),拒绝包含未解析<ENV_VAR>或\占位符的配置。 - 防止字面占位符字符串被当作真实 API key 发送到 LLM provider(难以诊断的 401 根因)。
- 首次运行跳过校验(
create_default_config模板场景)。
修复
切换话题后滚动到最新消息
- 修复切换话题后不滚动到最新消息的问题。
- 跟随意图仅由用户输入(wheel/touch/key)推翻,程序触发的滚动不会打断用户浏览。
- 将虚拟化
totalSize纳入滚动依赖,使测量收敛到真实底部。
WebSocket 重连竞态修复
- 修复 URL 切换时的 WebSocket 重连竞态问题。
- 事件处理引入代际同一性守卫,孤儿 socket 事件整体忽略。
- disconnect 恰好触发一次
onDisconnect,避免重复清理。
删除话题竞态修复
- 修复删除选中话题时的竞态问题。
- 乐观移除本地话题并以
null作为唯一无选择哨兵。 - 杜绝基于过期列表重选已删除话题。
重构
8 处 quick wins
shared.rs提取 channel/cli 适配器公共逻辑,消除 124 行重复代码。http_utils.rs提取 HTTP 响应读取公共逻辑,http_request.rs与web_fetch.rs共享实现。bash.rs/shell_session.rs简化冗余逻辑。gateway/mod.rs优化路由分支。storage/mod.rs精简查询逻辑。mcp/client.rs增强错误处理。
内部改进
- 修复 release 构建编译器警告:补全
regex::Captures显式生命周期标注,cfg(debug_assertions)条件化仅 debug 使用的变量,AnthropicProvider::llm_timeout_secs添加cfg_attr allow(dead_code)。 - 飞书 channel 时间戳去重改用
crate::utils::current_timestamp(),消除unwrap()panic 点并统一日志格式。 - 批量更新依赖 patch 版本(chrono, clap, anyhow, bytes 等),无 breaking change。
测试
cancel_manager.rs新增 8 个单元测试,覆盖 register/cancel/remove/overwrite/list/cancel_all/drop-safety 核心路径。session_pool.rs新增 3 个单元测试,覆盖is_scheduler_chat_id路由逻辑。- 配置占位符校验新增 11 个单元测试,覆盖空值、小写、数字、去重、多占位符、首次运行、加载集成等边缘场景。
0.3.3 - 2026-08-07
较 0.3.2 的 12 个 commit 迭代,聚焦 前端渲染性能飞跃、流式通信健壮性 与 代码质量治理 三大方向。
新增功能
执行状态对账端点
- 新增
GET /api/executionsHTTP 端点,返回后端权威的执行中话题集合。前端 WebSocket 重连时调用此端点对账,修正断连期间丢失的execution_completed信号导致的状态漂移。
性能优化
消息列表虚拟化(长对话不再卡顿)
- 引入
@tanstack/react-virtual替换原messages.map全量渲染,只渲染视口内 + overscan=6 条消息,DOM 节点数恒定。 measureElement动态测量变高度消息(一行文本 vs 50 行代码块),estimateSize=120提供初始估计,测量后自动校正。- Firefox 特殊处理
measureElement(getBoundingClientRect)。 - 适配现有功能:自动滚到底部改用
virtualizer.scrollToIndex;viewKey滚动位置记忆保留;highlightedMessageId先渲染目标项再 rAF 加 class;流式 delta 不计数(消息条数不变)。 - 性能对比(500 条消息):DOM 节点 10000+ → ~200;首次渲染数百 ms → <16ms;流式 diff 从全量列表降至仅可见项。
流式 delta 批处理(避免每 token 全数组拷贝)
- 用
streamingRef累加 delta chunks +requestAnimationFrame批量 flush,将每秒数十次 O(n) 数组拷贝合并为一帧一次状态更新。 useMessages.ts新增streamingRef累加器 + rAF 调度,所有 delta 只 push 到 ref,由flushStreaming批量落盘。useChat.ts5 处setMessages([])改为clearMessages(),切话题/会话/通道时重置流式 ref,避免脏状态残留。- 复杂度:O(n²·L) → O(n) 每帧。
改进
压缩阈值默认值下调
- 工程化压缩阈值
threshold_ratio从 0.7 下调至 0.5(50%),LLM 压缩阈值llm_compaction_threshold_ratio从 0.5 下调至 0.3(30%)。 - 降低触发门槛使压缩更积极介入,减少上下文溢出风险。同步更新相关注释、日志信息和前端 hint 文案。
修复
输入框/发送按钮状态按话题隔离
- 将单一全局
isLoading布尔值重构为按topic_id跟踪的processingTopicIds集合,isLoading派生自当前选中话题是否在集合中。 - 导航响应不再清空处理状态,切换话题后切回原话题仍能正确禁用输入。
- 重连时通过
/api/executions端点对账后端权威执行状态,修正断连期间丢失的execution_completed信号。
WebSocket 断连时清理流式状态
- 修复 WebSocket 在流式输出中途断连时
streamingRef(contentChunks/index)不重置,导致重连后新消息 delta 追加到旧消息错误位置。 - 修复链路:
useWebSocket的onDisconnect回调 →useChat的finishStreaming→useMessages的finishStreaming(重置 ref + flush pending chunks)。
会话消息泄露到定时任务视图
handleSchedulerMessage(Tier 1 路由)原先无条件吞掉所有可转换的 chat 消息,导致正在执行的实时消息被错误追加到调度器视图。- 修复:调度器视图只接收不带
topic_id的历史加载消息;实时流式消息和带topic_id的实时消息 fall through 到主视图。
重构
公共工具函数提取与 DRY
- 提取
src/utils.rs公共工具函数模块,消除跨模块重复逻辑。 - 修复飞书 channel 正则表达式重复编译问题,改为
Lazy<Regex>一次编译。 - 网关路由逻辑 DRY 化,减少
gateway/mod.rs重复代码。 agent_loop/providers/config/storage等多模块统一引用公共函数,20 个文件受影响。- CI 新增安全审计步骤(
cargo audit)。
内部改进
- 存储模块应用
rustfmt格式化(migrations.rs/row_mapping.rs/tests.rs)。 - 降低
list_todoshandler 与 gateway 转发日志级别为 debug,减少子代理多次更新待办时的 INFO 日志噪音。 - 删除临时优化计划文件
OPTIMIZATION_PLAN.md。
测试
- 新增 MessageList 虚拟化对抗性 smoke test(5 个用例):空消息渲染、100 条消息不崩溃、highlight 视口外不崩溃、viewKey 切换不崩溃、流式 rerender 不崩溃。
- 新增流式断连对抗性测试(2 个用例):
stream_end幂等性验证、多周期断连-重连循环下finishStreaming幂等验证。 - 新增断连后新 delta 不污染旧消息测试(用例 17)。
- 新增定时任务视图消息隔离测试(用例 16)。
- 新增批量 delta 累加与
stream_end后assistant_response替换对抗性测试。
0.3.2 - 2026-08-06
较 0.3.1 的 7 个 commit 迭代,聚焦 上下文压缩可配置化、网关安全加固、并发模型优化 与 错误防御性提升 四大方向。
新增功能
压缩算法关键参数暴露到设置页面
- 将 4 个上下文压缩参数从硬编码提取到
config.json顶层compaction节:threshold_ratio(0.7):工程化压缩触发阈值,占context_window的比例llm_compaction_threshold_ratio(0.5):LLM 压缩触发阈值truncate_max_tokens(100):工程化压缩时 tool 结果截断到的 token 数preserve_count(5):LLM 三段压缩保留最旧/最新的 unit 数
- 前端新增"上下文压缩"设置标签页(Archive 图标),4 个 number input 分两组展示。
ContextCompressor内聚所有压缩参数,新增with_compaction_config()构造函数和truncate_tool_results()方法。AgentLoop通过调用compressor.truncate_tool_results()实现零参数耦合,压缩参数变更仅影响ContextCompressor。
HTTP API 认证与 CORS 防护
- 新增 HTTP API 认证机制,未授权请求直接返回 401。
- CORS 防护:明确指定允许的 origin,阻止跨域未授权访问。
- 修复密钥泄露风险:敏感信息不再出现在错误响应中。
改进
上下文压缩重构为两阶段+双阈值+三段保留
- 两阶段压缩:工具调用完成后触发压缩流程,先用
prompt_tokens判断 70% 阈值。 - 阶段 1(工程化压缩):截断非子代理 tool 结果到约 100 token,仅改内存数据。
- 阶段 2(LLM 压缩):工程化压缩后若估算 token 仍超 50% 阈值,才调用 LLM 压缩。
- 三段保留:保留最旧 5 个 unit + 中间段 LLM 摘要 + 最新 5 个 unit,通过
HistoryUnit原子单元保证ToolRound不被拆分。 - LLM 压缩失败时降级为仅工程化压缩,不中断 agent loop。
迁移 parking_lot 锁并优化阻塞 IO 与内存管理
- 将
std::sync锁替换为parking_lot实现,减少锁竞争开销。 - 优化阻塞 IO 路径,避免热路径无谓阻塞。
- 内存管理改进:减少不必要的克隆与分配。
修复
子智能体任务状态卡死
- 修复已完成子智能体任务卡在"子智能体正在执行..."状态,前端无法正确展示结果。
飞书 channel 消息丢失
- 修正飞书 reaction 语义,与飞书 API 规范对齐。
- 增容 message bus 队列,避免高频消息场景下队列满导致最后一条消息丢失。
防御性错误处理
- 替换
unreachable!()宏调用为防御性错误返回,避免运行时 panic。 - agent/gateway 关键路径改用
Result传播错误,提升系统鲁棒性。
0.3.1 - 2026-08-05
较 0.3.0 的 19 个 commit 迭代,聚焦 历史压缩可追溯性、token 统计准确性、前端渲染稳定性、工具执行可靠性 与 网关吞吐优化 五大方向。
新增功能
历史压缩保留原消息(双视图分离)
- 压缩流程从物理删除原消息改为标记位
is_compacted分离两个视图:- LLM 视角(
load_messages_for_topic):只看is_compacted=0的压缩摘要 + 新消息,context 仍精简。 - UI 视角(
load_messages_for_topic_full):看原消息(含is_compacted=1)+ 新消息,排除压缩摘要,前端切回老话题仍能展示完整原始对话。
- LLM 视角(
- 新增
compact_topic_history:不删除原消息,仅打标记 + 插入摘要,同事务内删除旧摘要避免累积。修复 token 统计因压缩丢失usage的问题。 messages表新增is_compacted INTEGER NOT NULL DEFAULT 0列,migration 幂等。
Topic 维度 token 统计
- 新增
batch_topic_token_stats,按topic_id聚合 token 消耗,替代原按session_id聚合导致的同 session 多 topic 共享总和问题。 - 前端侧边栏每个 topic 显示独立 token 消耗与 context 占用百分比(Coins 图标 + 数值,绿/黄/红三色指示)。
- 主代理执行结束时触发
list_topics刷新(500ms 防抖),实时更新侧边栏 token 统计;子代理每轮执行也支持刷新。
设置页重启按钮
- 设置页 Footer 区新增重启按钮,样式为
bg-tertiary+ 边框,与主保存按钮区分。 - 确认对话框区分触发来源:保存后触发显示"配置已保存 / 稍后",手动触发显示"重启服务 / 取消"并警告未保存改动。
- 状态管理改用
restartDialogMode: 'saved' | 'manual' | null,按钮在重启期间显示 loading 并禁用。
设置页懒加载标签页与子代理管理
- 拆分设置页为懒加载标签页,减少首屏渲染负担。
- 前端支持子代理创建与删除,配合
PUT /api/subagents/update端点。
LLM 主调用可配置重试机制(0.3.0 收尾补充)
ProviderConfig增加max_retries字段(serde default=3,向后兼容)。agent_loop流式 + summary 两个调用点实现重试循环:指数退避 1s/2s/4s,仅对 429/502/503/504/timeout/connection reset 重试;流式仅在未 emit delta 时重试,避免重复输出。
修复
前端渲染稳定性
MessageBubble使用React.memo避免流式期间不必要重渲染。useWebSocket回调 ref-化,避免父组件重渲染触发 WebSocket 无谓重连。- 修复触发滚动到底部按钮时新消息计数错误。
- 修复话题重命名预填字段与写入字段不一致。
- 修复流式期间消息重渲染、WebSocket 无谓重连与新消息计数错误。
子智能体结果展示
- 失败/超时子智能体返回结构化结果,前端可点击查看详情,而非静默丢失。
Token 统计准确性
- 修复 token 统计按
session_id聚合导致同 session 多 topic 共享总和:改为按topic_id聚合,子代理消息通过session_id NOT LIKE 'sub:%'排除。 - 修复主代理执行结束后 token 统计不刷新:
useMessages在execution_completed事件时触发bumpTopicRefreshTrigger()。
工具执行可靠性
- 修复 shell 工具超时未生效:
adb start-server守护进程继承 stdout 管道导致 EOF 阻塞,adb devices误判 socket 等待为 stdin 等待绕过 deadline。新增STREAM_DRAIN_MS常量、改进kill_and_reap、移除should_return_pending中的错误检查,确保 timeout 参数完全覆盖默认值。
安全加固
web_fetch加固 SSRF 防护,禁用 HTTP 重定向,与http_request实现对齐。
MCP 兼容性
- 限制 MCP server 名称字符并兜底
tool_name清洗,避免非法字符导致 OpenAI API 400。
性能优化
网关吞吐
send_with_retry对ChannelFull错误短路(不重试、不退避),加速队列消费,避免 dispatcher 在满队列时 7s 退避阻塞。- 新增
ChannelError::ChannelFull变体,CliChannel在try_send返回Full时映射为ChannelFull。
存储查询
get_topic_message_count改用SELECT COUNT(*)在数据库侧计数,避免将所有消息(含content、tool_calls_json等大字段)加载到内存。
热路径优化
- 减少热路径无谓拷贝与重复正则编译,跳过已完成 migration。
内部改进
- 删除临时计划文件
PLAN.md。 - CHANGELOG 补充 LLM 重试机制条目并修正 commit 计数。
0.3.0 - 2026-08-04
较 0.2.0 的 18 个 commit 迭代,聚焦 Agent 执行与显示层解耦、LLM 调用稳定性、工程化基线、并发持久化稳定性、安全加固 与 MCP 兼容性 六大方向。锁屏冻结架构修复经五轮对抗性审查验证。
新增功能
话题重命名
- 新增
RenameTopic命令与TopicRenamed协议消息,复用存储层已有的update_topic_title方法。后端响应携带刷新后的完整 topic 列表,前端零额外往返同步侧边栏。 - 前端
TopicList侧边栏增加内联编辑入口:悬停显示铅笔图标,Enter 提交 / Esc 取消 / blur 取消,通过onMouseDown preventDefault防止按钮点击时 input 提前失焦。
前端自动构建集成
- 新增
build.rs,cargo build时自动执行npm install + npm run build,消除前后端构建割裂。支持SKIP_FRONTEND_BUILD环境变量跳过。
工程化基线
rustfmt.toml固化max_width=100/ 4 空格缩进;Cargo.toml配置[lints.rust]与[lints.clippy]渐进式规则。.github/workflows/ci.yml:Rust(fmt + clippy + test)+ 前端(eslint + tsc + test + prettier format:check)双平台 CI。Makefile新增check/fmt/fix目标,clippy 对齐--all-targets --all-features。- 前端 eslint flat config + prettier 配置,对 47 个前端文件统一格式化并在 CI 强制
format:check。
默认迭代上限调整
max_tool_iterations默认值调整为 1000,匹配长任务子代理的实际需求。
LLM 主调用可配置重试机制
ProviderConfig增加max_retries字段(serde default=3,向后兼容),透传至AgentRuntimeConfig归属 agent 行为层,不进ProviderRuntimeConfig以保持 provider 构造包纯净。agent_loop流式 + summary 两个调用点实现重试循环:指数退避 1s/2s/4s,仅对 429/502/503/504/timeout/connection reset 重试;流式仅在未 emit delta 时重试(AtomicBool跟踪),避免重复输出;退避 sleep 期间响应cancel_signal,取消优先。- 前端
ProviderConfig类型和表单增加max_retries字段。 - 7 个单元测试(3 判定 + 4 行为),540 个 lib 测试全绿。
架构修复
Agent 执行与显示层解耦(锁屏冻结根因修复)
根因:浏览器锁屏导致 WebSocket 半死,ws_sender.send().await 永久阻塞,级联阻塞 dispatcher → MessageBus → Agent Loop,后端停止执行直到解锁。
基于第一性原理建立"执行-显示解耦"原则:agent 执行只依赖 SQLite 持久化,实时广播是可丢弃的最佳努力通道。
MessageBus::publish_outbound由send().await改为try_send():bus 满时丢弃消息并告警,agent 不再被显示层阻塞。新增BusError::Dropped变体。- WebSocket writer task 包裹
tokio::time::timeout(30s):半死连接超时即关闭。使用每连接独立的CancellationToken(非共享的 CliChannel 级 token),避免一个连接超时关闭所有连接。writer 退出时 cancel 通知主 loop 退出,确保unregister_connection执行。 CliChannel::send由send().await改为try_send():dispatcher 单线程顺序处理,原阻塞式发送在 writer 卡住时会阻塞所有连接 37s,改后立即返回。- 全仓 13 处
publish_outbound调用统一区分Dropped(warn,预期背压)/Closed(error,异常)日志级别,消除监控噪音。scheduler 的 3 处?改为 warn,避免Dropped触发 misfire 重试风暴。 - 前端 WebSocket 添加 25s 客户端 ping + 指数退避重连(3s→6s→12s→24s→60s 封顶,上限 999 次)。重连后区分"重连恢复"与"首次/切换通道":前者保留断连前 messages 并刷新 topic 列表,后者清空数据避免污染。
安全加固
SSRF 重定向绕过修复
web_fetch工具禁用 HTTP 重定向(redirect::Policy::none()):原validate_url只校验初始 URL 的 host,跟随 302 跳转可重定向到169.254.169.254(云元数据)或127.0.0.1等内网地址,绕过is_private_host的 SSRF 防护。与http_request工具保持一致。
Safety Guard 正则收紧
format正则收紧为\bformat\s+.*[a-z]:,要求出现盘符才拦截,避免误伤dart format、buf format、pytest --format等合法命令。- 按平台分组注入规则,Unix 不再注入 Windows 专用规则;
Remove-Item正则改为小写,与guard_command的大小写处理一致。
稳定性修复
SQLite 并发写入死锁
- 7 个写事务从
BEGIN DEFERRED改为BEGIN IMMEDIATE:在事务开始即获取写锁,消除多 sub-agent 并发写入时的死锁路径。busy_timeout从 5s 提升至 30s。 - 根因:
BEGIN DEFERRED下多个事务可同时读MAX(seq)不持写锁,提交时互相阻塞,5s timeout 耗尽后返回SQLITE_BUSY。BEGIN IMMEDIATE强制写者串行排队,顺带消除MAX(seq)+1竞态导致的 UNIQUE 约束冲突。
测试与代码质量
- 修复
anthropic错误链嵌套测试为真正的#[source]链(原测试是无效的,inner 变量被let _抑制)。 - 补充
anthropicprovider 15 个纯函数单测(原 396 行零测试),覆盖 data URL 解析、图片过滤、字段过滤、响应反序列化、错误链格式化。 - 修复 3 个失败测试:
agent_md_template写入模板内容 /StreamingAccumulatorBTreeMap 保序 /source_order断言补全。 - 清理未使用的 dead code 函数与方法。
- 新增
ARCHITECTURE.md架构文档,聚焦数据流与 7 个关键设计决策。
CI 覆盖范围扩大
cargo build --lib改为cargo build,确保main.rs二进制入口被编译验证。cargo test --lib改为cargo test,纳入tests/目录集成测试。test_request_format.rs的 8 个序列化测试此前从未在 CI 中运行。
跨平台构建修复
- 修正依赖分类错误:
rmcp/schemars/http/tower-http/rust-embed均为跨平台 crate,错放在[target.'cfg(windows)'.dependencies]下导致 Linux 构建失败,移出 target 段。
MCP 工具名清洗
- OpenAI 要求 function name 匹配
^[a-zA-Z0-9_-]+$,否则整个请求 400。MCP 工具名由mcp_{server_key}_{tool_name}拼成,两个输入源分别处理: - 后端:
sanitize_tool_name替换tool_name中的非法字符(.,:,/等)为_,保留server_key和tool_name原值用于路由,仅清洗 LLM 可见的full_name,发生清洗时打 warn 日志便于定位。 - 前端:MCP 卡片头部改用
MapEntryHeader支持点击重命名,addMcp/renameMcp正则校验 server 名称 + toast 提示。顺手修了MapEntryHeader进入编辑时val未同步当前name的 bug。
0.2.0 - 2026-07-31
较 0.1.2 的 47 个 commit 迭代,聚焦 能力策略、模型独立配置、话题级并发隔离 与 Agent Loop 性能优化 四大方向。
新增功能
能力策略(CapabilityPolicy)统一模型
- 新增
CapabilityPolicy领域模型,统一管理专家/子代理/技能的allowed_skills/denied_skills/allowed_tools/denied_tools四类白/黑名单。 - 专家和子代理的 Markdown frontmatter 支持上述四类字段,在
create_agent时按策略过滤ToolRegistry(快照语义)。 - 子代理支持数据驱动的工具过滤,删除旧版内置
explore白名单。 - 新增 HTTP 端点
GET /api/tools与PUT /api/subagents/update,供前端动态加载工具清单与更新子代理配置。 - 前端引入通用
CheckboxList勾选组件,将 capability 字段从自由文本 textarea 改为按来源分组的勾选式编辑,避免手输工具名。
模型独立配置
- 专家和子代理的 Markdown frontmatter 新增
provider与model可选字段,引用config.json中的providers/models表,可独立指定模型而不再继承主 agent。 - 主 agent 支持会话级模型覆盖(
provider/model在配置层覆盖)。 - 前端编辑模态框新增"模型配置"卡片,含 provider/model 下拉选择,选项由
GET /api/model-options提供。 - 专家引用不存在的 provider/model 时阻断会话并报错;子代理引用失败时将错误回传给 LLM。
话题级并发隔离
- 实现聊天消息串行锁,确保同一聊天的消息处理串行执行。
- 串行锁按
topic_id键化,支持多话题并发执行,互不阻塞。 topic_id全程显式传递(从消息接收到历史加载),修复消息错投与并发阻塞。- 内存历史缓存按
topic_id键化(原按chat_id),修复 DB 压缩时的 TOCTOU 覆盖问题。
子代理嵌套深度配置
- 暴露
tools.task.max_nesting_depth为可配置项(默认 2),前端"Task 子代理"卡片新增输入框。 - 保留双重防护:工具调用前校验 + 工具集构造时按深度移除
task工具。
专家配置热更新
- 专家配置保存后即时生效,无需重启网关。
工具调用序列前向检查
- 添加工具调用序列的前向校验,确保 tool 消息紧随 assistant 的 tool_calls 消息,避免 OpenAI/DeepSeek API 400 错误。
前端测试基础设施
- 引入 vitest 测试基础设施,添加
useChat handleServerMessage特征测试。
性能优化
Agent Loop 性能(P0)
- 工具定义缓存:
get_definitions()从每轮迭代调用一次改为process()循环外构建一次。基于快照语义——单次process()内Arc<ToolRegistry>不变,专家切换只影响下一次create_agent。 - 轻量 token 估算:新增
estimate_text_tokens_from_chat_messages,直接基于ChatMessage累加字段长度,消除中间text_only_messages: Vec<Message>构造(原方案每条消息 × 5 字段双克隆)。 - 工具 token 估算循环外预算:
serde_json::to_string全量序列化工具定义从每轮一次降为process()内一次。 - DB 写 offload:
PersistingEmittedMessageHandler用tokio::task::spawn_blocking包装 SQLite 同步写,解除 tokio worker 线程阻塞,不改变失败语义(仅记日志不阻断主流程)。
SessionPool 锁范围收敛
ensure_session_internal改为 double-checked locking:先短暂持锁检查存在性,释放锁后执行耗时的 session 创建(含配置加载、agent 工厂构造),再次持锁插入并处理竞态。避免跨session_factory.create().await持有全局锁导致所有 channel 的 session 访问串行化。
修复
安全修复
- 修复 SSRF 重定向绕过漏洞。
- 修复符号链接路径遍历漏洞。
- 修复
TodoItemSummary字段缺失。
并发与稳定性
replace_todos用transaction()包裹 DELETE + INSERT,保证原子性——中途失败自动回滚,避免 todos 列表丢失。事务内复用同一连接查询返回值,消除drop(conn)后重新pool.get()的冗余。- 修复话题隔离下
topic_id全程显式传递,解决消息错投与并发阻塞。 - 修复内存历史按
topic_id键化,新增replace_topic_history修复 DB 压缩覆盖。 - 修复
http.rs重启信号吞错(P1)。 - 修复 prompt 注入吞错(P0)。
前端修复
- 修复点击设置后白屏:React hooks 顺序违规(
useEffect放在条件 return 之后导致 #310 错误)。 - 修复
useEffect依赖项缺失(P0)。 - 修复子智能体视图间歇性丢消息:同步前置
subAgentViewRef/subAgentStackRef。 - 修复子智能体工具消息去重:改为按
id + type去重,修复工具状态卡在执行中。 - 修复高亮消息时退出子智能体视图的问题。
- 修复专家发现与前端选择多项问题。
- 兼容
base_url末尾斜杠,避免拼接产生双斜杠导致 404。 TodoWriteToolmerge 模式内存为空时从 DB 回填,防止丢失旧项。
依赖与构建
- 升级 wechatbot 的
reqwest至 0.13,消除版本冲突。 - 将
rmcp依赖从 git branch 迁移到 crates.io 版本。 - 提交
Cargo.lock以保证二进制构建可复现(binary 项目约定)。
重构
前端架构
- 重写
useChat为组合根,消除上帝 Hook。 - 抽取
useChat的领域子 hook 与messageMappers。 - 建立前端 API 客户端层,消除硬编码路径与重复
fetch。 - 拆分
ConfigPage.tsx与storage/mod.rs(P2)。 - 清理 P0/P1 技术债(
any类型、React key、dead_code、硬编码 URL)。
后端架构
- 重构
AgentLoop中的消息处理逻辑,简化工具结果处理和 LLM 请求构建。 - 重构工具提示提供者,整合工具使用说明;删除冗余的
TodoPromptProvider。 get_current/save_topic直读 DB 加载消息,移除SessionManager依赖。- 改用
gray_matter解析 Markdown frontmatter,增加相应日志。 - 优化工具使用说明,简化记忆检索和写入规则。
- 移除未使用的
cli_sessions变量,优化ws.rs中的代码。
内部改进
- 增加整理意识,确保同类工作输出到同一文件夹。
- 修复 MCP 日志输出。
0.1.2 - 2026-07-28
新增
- WebSocket 连接泄漏修复,使用
CancellationToken实现优雅重启。 - 交互式 Shell 会话管理。
- 数据库连接池优化会话存储,新增错误处理。
- 平台特定的进程输入等待检查,增强 Bash 工具的用户授权检测。
- 前端静态文件嵌入二进制。
- React Web UI 前端界面。