feat: 后台服务模式 + 日志滚动 + 修复 llm_usage 表兼容性

- 新增 logger.rs(tracing-appender,日滚日志,.data/logs/)
- service 子命令:等同 listen --llm 但日志同时写入文件
- systemd/ias.service 单元文件
- 迁移 0007:ALTER TABLE llm_usage ADD COLUMN IF NOT EXISTS
  修复与 iPet 旧表的结构冲突
- ias usage 命令可正常查询 Token 统计
- 日志滚动保留 7 天,自动删除旧文件
This commit is contained in:
2026-06-01 17:45:17 +08:00
parent b9de3665d9
commit 00002e4740
13 changed files with 341 additions and 45 deletions
+30 -18
View File
@@ -64,29 +64,41 @@ impl MemoryStore {
}
}
/// read_summaries 工具:读取历史摘要
/// read_summaries 工具:读取历史摘要(内存 + 数据库)
pub async fn read_summaries(
session: &Arc<Mutex<super::types::ChatSession>>,
) -> String {
let s = session.lock().await;
if s.summaries.is_empty() {
let mut lines: Vec<String> = Vec::new();
// 内存中的摘要
for sum in &s.summaries {
let reason = match sum.reason {
super::types::SummaryReason::Overflow => "上下文压缩",
super::types::SummaryReason::Timeout => "空闲超时",
};
lines.push(format!(
"[{}] {} (原因: {})",
sum.created_at.format("%Y-%m-%d %H:%M"),
sum.text,
reason,
));
}
// 数据库中的历史摘要
if let Some(pool) = &s.db_pool {
if let Ok(db_summaries) = crate::db::models::load_summaries(pool, 5).await {
for text in db_summaries {
if !lines.iter().any(|l| l.contains(&text.chars().take(30).collect::<String>())) {
lines.push(format!("[数据库存档] {}", text));
}
}
}
}
if lines.is_empty() {
"暂无历史摘要".to_string()
} else {
s.summaries
.iter()
.map(|sum| {
let reason = match sum.reason {
super::types::SummaryReason::Overflow => "上下文压缩",
super::types::SummaryReason::Timeout => "空闲超时",
};
format!(
"[{}] {} (原因: {})",
sum.created_at.format("%Y-%m-%d %H:%M"),
sum.text,
reason,
)
})
.collect::<Vec<_>>()
.join("\n---\n")
lines.join("\n---\n")
}
}