fix(agent-memory): yaml-escape hint values in memory_observe and add max_hint_bytes config#1154
Conversation
Review — fix(memory): yaml-escape hint values in memory_observe
结论按 block / suggest / clean 分级。 block — 修复基于误诊,且对反斜杠引入回退
三者都是手写逐行解析:
正确修法二选一:① 写入与读取都改用真正的 YAML 序列化/解析(加 suggest — 缺少 round-trip 测试新增 9 个 clean
建议:命名 amend + 改用上述任一正确修法 + 补 round-trip 测试后重新提审。 |
e2690dc to
a8efb8f
Compare
|
Hi @shiloong — gentle ping on this PR. It's been 10 days without review. Rebased today onto latest main (v0.2.1 + CJK LIKE fallback + hermeticized tests). No conflicts. Quick summary for reviewer:
Why 512 bytes: follows the existing MemoryConfig pattern — a hint is metadata, not content, so 512 bytes is generous enough for a useful one-sentence summary while preventing abuse. Configurable via cc @Forrest-ly (for memory review — similar area to the CJK recall fix from 7/4) Would appreciate a review when you have bandwidth. Thanks! (If there's another memory maintainer I should tag instead, happy to redirect.) |
|
@ralf003 Re-ping after the rebase — checking the latest diff, the two block-level items from my earlier review (#1154 (comment)) are still unaddressed, and the commit subject is still 1. The
|
| hint input | written line | read-back value |
|---|---|---|
C:\Users\admin (was correct before this PR) |
hint: "C:\\Users\\admin" |
C:\\Users\\admin ← doubled backslashes, regression |
she said "hi" |
hint: "she said \"hi\"" |
she said \"hi\" ← literal backslash-quote remains |
Before this PR, C:\Users\admin round-tripped correctly (single \ preserved); after, it comes back as C:\\Users\\admin. That's a real correctness regression on the actual read path.
Ask
Could you either:
- (a) point me to a YAML-parser read path I missed (in which case the escape is correct and I'll withdraw), or
- (b) adopt one of the two correct fixes:
- add
serde_yamland use it for both write and read of frontmatter (shared module), or - revert to the pre-PR unquoted form (
h.replace('\n', " ")) — which is already sufficient for the hand-rolled parser, since the only real risk is\n---\nearly-terminating the block, and newline→space already covers it.
- add
The max_hint_bytes cap and MEMORY_MAX_HINT_BYTES env override are fine independently — keep those regardless.
3. Missing round-trip test
The 9 new yaml_escape_hint unit tests only assert the escaped output form. Please add at least one test that writes via memory_observe and reads back via the real parse_frontmatter_flat, asserting the original hint survives — that's the test that would have caught the backslash regression above.
4. Naming (reminder)
Commit subject is still fix(agent-memory): …. Per .github/commitlint.config.json scope-enum and every existing src/agent-memory/ commit, the scope is memory (also matches #1038 docs(memory) / #1043 test(memory)). Please amend to fix(memory): … (no new commit).
Happy to be corrected on (a) if I missed a parser.
a8efb8f to
af35573
Compare
…bytes config
- Replace yaml_escape_hint() with sanitize_hint() that only replaces
newlines and ASCII control chars with spaces, without YAML-style
double-quoting or backslash escaping. The hand-rolled frontmatter
readers (parse_frontmatter_flat / extract_title_and_description)
use split_once(": ") + trim_matches('"') and do NOT interpret
YAML escapes, so YAML escaping is asymmetric and causes a round-trip
regression on Windows paths containing backslashes.
- Add max_hint_bytes (default 512) to MemoryConfig with
MEMORY_MAX_HINT_BYTES env var override.
- Add 8 unit tests for sanitize_hint plus a round-trip test that
validates hints through the real parse_frontmatter_flat reader.
- Update memory_observe signature to accept &MemoryConfig;
propagate config through MemoryService facade and MCP server.
af35573 to
cb36574
Compare
|
@shiloong ready for re-review. Changes since last review:
PTAL, thanks! |
Problem
memory_observewrites the model-providedhintvalue into YAML frontmatter with minimal sanitization — only newlines are replaced with spaces. YAML special characters (#comment,:key-value separator, quotes, backslashes) can corrupt the frontmatter block. For example,hint: fix #123 and #456is truncated by the YAML parser atfixbecause#starts a comment.Additionally, there is no size limit on the hint field, unlike
max_read_bytes/max_write_bytes/max_append_bytesfor other MemoryConfig fields. A rogue or misconfigured model could inject arbitrarily long hints.Changes (116 lines, 3 files)
src/tools/memory_observe.rsyaml_escape_hint()function (~20 lines) that double-quotes hint values and escapes",\,\n/\r, and ASCII control characters for safe YAML inclusionmax_hint_bytesenforcement (default 512) — hints exceeding the limit are rejected withInvalidArgument#comment characters, colons, quotes, backslashes, multiline, empty strings, control chars, and normal textsrc/config.rsmax_hint_bytes: u64toMemoryConfigwith default 512default_max_hint_bytes()functionMEMORY_MAX_HINT_BYTESenv var override inapply_env_overrides()Service layer propagation
src/service/mod.rs: pass&self.config.memorythrough totools::memory_observe(no signature change at service level)Verification
yaml_escape_hinttests pass