feat(memory): add memory_sessions and memory_timeline tools#1120
feat(memory): add memory_sessions and memory_timeline tools#1120shiloong wants to merge 1 commit into
Conversation
Forrest-ly
left a comment
There was a problem hiding this comment.
PR #1120 Review — feat(memory): add memory_sessions and memory_timeline tools
本 PR 添加 2 个跨 session 查询工具:memory_sessions(列出 facts/summary/ 中的历史 session 摘要)和 memory_timeline(展示指定 session 的工具调用时间线,读取 .anolisa/session-logs/.jsonl)。同时将 incremental_interval 默认值从 20 改为
0(实际为死代码清理)。另有 3 个空文件被意外提交。
306 行新增、20 行删除、9 个文件。
发现
- src/agent-memory/src/tools/session_history.rs:~235 — memory_timeline 未校验 session_id,存在路径穿越风险 (CONFIRMED, 高)
let log_path = svc.mount.meta_dir
.join("session-logs")
.join(format!("{session_id}.jsonl"));
session_id 直接来自 MCP 客户端参数,无任何校验。如果传入 ../../etc/shadow 等包含 .. 的值,将构造 .anolisa/session-logs/../../etc/shadow.jsonl 并尝试用 std::fs::read_to_string 读取。虽然 .jsonl
后缀限制了文件名,但在有目标文件名匹配时仍可读取。代码库中已有现成模式:ns/mod.rs:181 和 snapshot/tar.rs:63 均做了 id.contains("..") 校验。此处缺失。
- src/agent-memory/config.rs, lib.rs, main.rs — 三个空文件意外提交到 crate 根目录 (CONFIRMED, 中)
Diff 显示在 src/agent-memory/ 目录下(而非 src/agent-memory/src/)新增了 3 个 0 字节文件(git hash e69de29bb)。真正的源文件在 src/agent-memory/src/{config,lib,main}.rs。这些空文件对编译无影响(Cargo 只看 src/
目录),但会造成目录污染和混淆。应删除。
- src/agent-memory/src/tools/session_history.rs:~247 — memory_timeline 将整个 JSONL 文件读入内存后再截取尾部 (CONFIRMED, 低-中)
let content = std::fs::read_to_string(&log_path)?;
// ... parse ALL lines ...
if entries.len() > limit {
entries = entries[entries.len() - limit..].to_vec();
}
长期运行的 session 可产生数千条 audit 记录。当前实现读取全部内容、解析所有行、构建完整 Vec,最后只取末尾 N 条。对于大文件可能造成不必要的内存压力。可改为从文件尾部反向读取或使用 BufReader + lines() 只保留最后 N 条。
- src/agent-memory/src/tools/session_history.rs:~324 — parse_count_from_body 中 "次" 匹配过于宽泛 (CONFIRMED, 低)
if line.contains(keyword) || line.contains("次") {
任何包含 "次" 的行都会触发数字提取,无论是否与目标 keyword 相关。例如 body 中有 "这是第3次代码重构",在搜索 "tool calls" 时也会匹配该行并返回 3。"次" 应作为 keyword 匹配的中文等价,而非与 keyword 并列的独立条件——或者改为
line.contains(keyword) || (keyword == "tool calls" && line.contains("次")) 之类的限定。
- src/agent-memory/src/tools/session_history.rs:~167 — memory_sessions 未使用 safe_fs,直接 fs::read_to_string (PLAUSIBLE, 低)
与代码库中其他读取路径(extractor.rs、write.rs、consolidation/writer.rs)使用 safe_fs (openat2 + RESOLVE_BENEATH) 不同,本 PR 的两个工具均使用 std::fs 直接操作。对于 memory_sessions(路径由服务端构造,风险低),这尚可接受;但对于
memory_timeline(路径包含用户输入的 session_id),缺少 safe_fs 加剧了 Finding #1 的风险
Session history query tools: - memory_sessions(limit): list historical session summaries from facts/summary/ directory. Returns session_id, created_at, tool_calls, tools_used, files_modified, description. - memory_timeline(session_id, limit): show tool call timeline from persistent session logs (.anolisa/session-logs/<sid>.jsonl). Returns timestamped entries with tool name, path, status, errors. Helper functions: - parse_frontmatter_flat(): extract key:value from YAML blocks - extract_body(): get markdown body after frontmatter - parse_count_from_body(): find numeric counts in text - parse_list_from_body(): extract comma-separated lists Tests: 5 new session history tests Total: 0 failures Tools: 23 total (was 21) Signed-off-by: Shile Zhang <shile.zhang@linux.alibaba.com>
dbe0663 to
c9a0860
Compare
Review 修复回复1. memory_timeline 路径穿越 — ✅ 已修复在 2. 三个空文件意外提交 — ✅ 已删除
3. 全量读取 JSONL 后截取尾部 —
|
Description
Add cross-session memory query tools:
facts/summary/directory. Returns session_id, created_at, tool_calls, tools_used, files_modified, description..anolisa/session-logs/<sid>.jsonl). Returns timestamped entries with tool name, path, status, errors.These tools enable agents to query and browse memories from previous sessions, supporting cross-session knowledge continuity.
Related Issue
no-issue: cross-session memory query tools
Scope
memory(agent-memory)Checklist
cargo clippy --all-targets -- -D warningspassescargo fmt --checkpassescargo testpasses (149 tests)