修复: run_command 空路径报错 + 隧道日志洪水 + 启动残留清理

- tool_registry: run_command working_dir 空字符串 "" → None,修 Windows os error 123
- lib: tunnel subscriber 从频率压制(suppress_until)改为连接状态感知(is_connected),
  断开时静默丢弃事件,重连后恢复透传,记 INFO 状态变迁(治本)
- conversation_repo: 新增 cleanup_stale_pending(),超 24h 残留 pending 标记 interrupted
- restore: 启动时先清理过期 pending 再恢复审批
- state: 实现 cleanup_orphan_pending_messages(),启动时清理对应已决/超时 tool 的
  __PENDING__ 占位消息
This commit is contained in:
lxy
2026-07-02 15:47:47 +08:00
parent d99a65f034
commit b18740405c
5 changed files with 68 additions and 2 deletions
+25
View File
@@ -264,6 +264,11 @@ impl AppState {
// 从 Settings KV 恢复审批超时配置(默认 15 分钟,0=禁用超时)。
state.reload_approval_timeout().await;
// 启动时清理残留 __PENDING__ 占位消息(对应 tool_execution 已非 pending 状态)
if let Err(e) = cleanup_orphan_pending_messages(&state.db).await {
tracing::warn!("清理孤儿 __PENDING__ 消息失败(非阻断): {}", e);
}
// 迁移旧 .trash(编译期 workspace_root → 运行期 data_dir),仅一次,幂等。
let old_trash = workspace_root_path().join(".trash");
let new_trash = data_dir.join(".trash");
@@ -554,6 +559,26 @@ fn build_registry(db: Arc<Database>) -> NodeRegistry {
registry
}
/// 启动时清理孤儿 `__PENDING__` 占位消息。
///
/// 对应 `tool_execution` 已非 pending(已审批/已超时/已中断)的占位消息是残留垃圾,
/// 不删会导致前端展示冗余的 pending 态工具卡。
pub async fn cleanup_orphan_pending_messages(db: &Database) -> anyhow::Result<u64> {
let conn_arc = db.conn();
let guard = conn_arc.lock().await;
let deleted = guard.execute(
"DELETE FROM ai_messages \
WHERE (content = '__PENDING__' OR content LIKE '%__PENDING__%') \
AND tool_call_id IS NOT NULL \
AND tool_call_id NOT IN (\
SELECT tool_call_id FROM ai_tool_executions WHERE status = 'pending'\
)",
[],
)?;
tracing::info!("清理孤儿 __PENDING__ 消息: {} 条", deleted);
Ok(deleted as u64)
}
#[cfg(test)]
mod tests {
use super::*;