## 锁迁移:std::sync → parking_lot 消除锁中毒(poison)导致的级联崩溃风险。parking_lot 锁不会中毒, 且性能更优。迁移覆盖全部生产代码: - experts/mod.rs: 4 RwLock + 13 expect - skills/mod.rs: 1 RwLock + 11 expect - tools/registry.rs: 1 RwLock + 2 expect - gateway/model_selection.rs: 1 RwLock + 2 expect - tools/task/repository.rs: 1 RwLock + 4 unwrap - tools/task/runtime.rs: 2 RwLock + 17 expect - gateway/session.rs + task/runtime.rs: stream_message_id Mutex - gateway/processor.rs: description_generation_in_flight Mutex - command/handler.rs + help.rs: metadata Mutex(公开 API) - mcp/client.rs: stderr_lines Mutex 测试代码中的 std::sync::Mutex(串行化锁 + TestObserver)有意保留, 已通过 unwrap_or_else(|err| err.into_inner()) 做中毒恢复。 ## P1: 阻塞 IO 迁移到 spawn_blocking 将 3 处阻塞 async worker 的操作迁移到 blocking 线程池: - file_read.rs: read_to_string + 行处理 + base64 编码整体包入 spawn_blocking - agent_loop.rs: 新增 preencode_images_for_request 两阶段预编码 (顺序分配预算 → 并行 spawn_blocking 编码),build_llm_request 改为 async - wechat.rs: media_to_send_content 改为 async,std::fs::read 用 spawn_blocking 包裹 ## P2: session_history topic_histories 内存上限 新增 MAX_CACHED_TOPICS=32 上限和 evict_inactive_if_needed 方法。 超限时驱逐非活跃 topic(不在 chat_topic_ids、不在 compression_in_flight、 serial_lock 未被持有)。活跃 topic 永不误驱逐。 remove_history 同步清理 topic_serial_locks,防止无限增长。 ## P3: 减少 panic 面 agent_loop.rs retry 循环的 response.expect(...) 改为 ok_or_else(...)? 返回 AgentError::Other,逻辑 bug 不再导致整个 agent 崩溃。 ## 对抗性审查修复 - preencode_images_for_request: 用 seen HashSet 去重,防止同 path 重复 编码导致 HashMap entry 覆盖(NoBudget 覆盖 Encoded 等) - evict_inactive_if_needed: 检查 topic_serial_lock.try_lock(),防止驱逐 正在 agent 处理中的 topic(original_topic_id 不在 chat_topic_ids 但 agent 仍持锁) - remove_history: 清理 topic_serial_locks ## 验证 - cargo check: 通过(仅既有 lifetime 警告) - cargo test: 559 passed / 3 failed(均为环境/sandbox 权限问题,与本次改动无关)
83 lines
2.6 KiB
TOML
83 lines
2.6 KiB
TOML
[package]
|
||
name = "picobot"
|
||
version = "0.3.1"
|
||
edition = "2024"
|
||
|
||
[lints.rust]
|
||
# 编译期硬错误:避免明显的内存安全/正确性隐患
|
||
unsafe_op_in_unsafe_fn = "warn"
|
||
rust_2018_idioms = "warn"
|
||
|
||
[lints.clippy]
|
||
# 渐进式策略:
|
||
# - 不直接声明 lint group(correctness/suspicious/complexity/perf),
|
||
# 因为 lint group 在 [lints] 中需用 priority 语法,简单 = "warn" 会报错;
|
||
# 且 clippy 默认已把 correctness 设为 deny,无需重复声明。
|
||
# - 仅显式 warn 少量高价值且存量不大的具体规则,避免一上线淹没在噪音中。
|
||
# 后续随着存量问题清理,可逐步把 unwrap_used/expect_used 升级为 warn。
|
||
redundant_clone = "warn"
|
||
dbg_macro = "warn"
|
||
print_stderr = "warn"
|
||
print_stdout = "warn"
|
||
|
||
[dependencies]
|
||
reqwest = { version = "0.13.2", default-features = false, features = ["json", "rustls", "multipart", "stream"] }
|
||
dotenv = "0.15"
|
||
serde = { version = "1.0", features = ["derive"] }
|
||
regex = "1.0"
|
||
serde_json = "1.0"
|
||
serde_yaml = "0.9"
|
||
async-trait = "0.1"
|
||
thiserror = "2.0.18"
|
||
tokio = { version = "1.0", features = ["full"] }
|
||
tokio-util = { version = "0.7", features = ["rt"] }
|
||
uuid = { version = "1.0", features = ["v4"] }
|
||
axum = { version = "0.8", features = ["ws"] }
|
||
tokio-tungstenite = { version = "0.29.0", features = ["rustls-tls-webpki-roots", "rustls"] }
|
||
futures-util = "0.3"
|
||
clap = { version = "4", features = ["derive"] }
|
||
dirs = "6.0.0"
|
||
prost = "0.14"
|
||
tracing = "0.1"
|
||
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
||
tracing-appender = "0.2"
|
||
anyhow = "1.0"
|
||
chrono = { version = "0.4", features = ["serde"] }
|
||
chrono-tz = "0.10"
|
||
cron = { version = "0.13", features = ["serde"] }
|
||
iana-time-zone = "0.1"
|
||
mime_guess = "2.0"
|
||
base64 = "0.22"
|
||
image = { version = "0.25", default-features = false, features = ["jpeg", "png", "gif", "webp"] }
|
||
tempfile = "3"
|
||
meval = "0.2"
|
||
rusqlite = { version = "0.39", features = ["bundled"] }
|
||
r2d2 = "0.8"
|
||
r2d2_sqlite = "0.34"
|
||
rustls = { version = "0.23", features = ["ring"] }
|
||
subtle = "2.6"
|
||
parking_lot = "0.12"
|
||
wechatbot = { path = "vendor/wechatbot" }
|
||
encoding_rs = "0.8"
|
||
libc = "0.2"
|
||
gray_matter = { version = "0.2", default-features = false, features = ["yaml"] }
|
||
# MCP (Model Context Protocol) support
|
||
rmcp = { version = "1.7", features = [
|
||
"client",
|
||
"transport-child-process",
|
||
"transport-streamable-http-client-reqwest",
|
||
"reqwest",
|
||
] }
|
||
schemars = "1.0"
|
||
http = "1"
|
||
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
||
rust-embed = "8"
|
||
|
||
[target.'cfg(windows)'.dependencies]
|
||
windows-sys = { version = "0.59", features = [
|
||
"Win32_System_Threading",
|
||
"Win32_System_Diagnostics_Debug",
|
||
"Win32_Foundation",
|
||
"Win32_System_Kernel",
|
||
] }
|