Conversation
The localfs write implementation was ignoring the WriteFlag parameter and not truncating the file when WriteFlag::Create or WriteFlag::Truncate was specified. This caused files to be appended instead of overwritten when writing empty content. Root cause: The _flags parameter was declared but never used. When opening an existing file, .truncate(true) was not called. Fix: Use OpenOptions::new().truncate(should_truncate) based on the flags. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…traction - Add workaround to delete messages.jsonl before writing to work around RAGFS localfs not truncating files (now fixed in ragfs) - Add _get_latest_archive_last_msg_time to filter messages for memory extraction by timestamp - Fix memory extraction to only process new messages after last archive Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
过滤 HEARTBEAT 健康检查消息,避免 HEARTBEAT.md 和 HEARTBEAT_OK 进入 session 存档。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverting to use logger.warn directly. The warnOrInfo wrapper was unnecessary as logger always has warn method. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ragfs localfs write now respects WriteFlag to truncate files, so the workaround to delete messages.jsonl before writing is no longer needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove old addSessionMessage (string content) - Keep addSessionMessage but accept parts array - Update index.ts and context-engine.ts to use new format - Update tests to check parts structure Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TypeScript strict mode requires handling possibly undefined warn method. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add trace_id to CommitSessionResult type and log it for all commitSession calls (afterTurn, commitOVSession, compact). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add toolInput field to ExtractedMessage type - Extract tool_input from msg.toolInput in extractNewTurnMessages - Pass tool_input when constructing tool parts for addSessionMessage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When extracting toolResult messages, look up the corresponding toolInput from the preceding assistant messages' toolUse blocks using toolCallId/ toolUseId as the key. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support additional field names: arguments, toolInput, tool_call_id Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scan all messages to find toolCall/toolUse/tool_call blocks - Extract tool input from arguments/input/toolInput fields - Match toolResult with toolCall using toolCallId/toolUseId Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
qin-ctx
left a comment
There was a problem hiding this comment.
Thanks for the PR. I left 4 blocking comments.
The main issues are: tool-call history no longer round-trips through afterTurn -> commit -> assemble; get_session_context() silently removes pre_archive_abstracts even though the public contract and consumers still require it; archive summaries are now generated from the filtered extraction subset instead of the actual archived message set; and compacted system-message extraction currently captures from the first ] instead of the last one.
CI is also failing on this branch: lint reports unused locals in session.py, and API integration tests already fail on the missing pre_archive_abstracts contract.
| : undefined); | ||
| if (output) { | ||
| result.push({ | ||
| role: "user", |
There was a problem hiding this comment.
[Bug] (blocking) This persists tool results as a user message containing a tool part, but the assemble path only reconstructs tool calls/results from tool parts on assistant messages and only when tool_id is present. extractNewTurnMessages() also does not persist the original tool call id, so a tool turn cannot round-trip through afterTurn -> commit -> assemble: the next assemble loses the toolUse/toolResult structure entirely. Please persist a stable tool identifier and store tool-call/tool-result data in a shape that the reader can actually reconstruct.
| task_id=task.task_id, | ||
| archive_uri=archive_uri, | ||
| messages=messages_to_archive, | ||
| messages=messages_for_extraction, |
There was a problem hiding this comment.
[Bug] (blocking) messages_for_extraction is passed straight into _run_memory_extraction(), but that method also generates the archive summary and writes .abstract.md / .overview.md. That means the timestamp filter now changes the archive metadata as well, not just the memory-extraction input. If any archived messages are filtered out here, the summary no longer describes the actual messages.jsonl that was written for this archive. The filter should apply only to the extraction input, not to archive rendering.
| latest_archive["overview"] if include_latest_overview else "" | ||
| ), | ||
| "pre_archive_abstracts": included_pre_archive_abstracts, | ||
| # 不再返回 pre_archive_abstracts |
There was a problem hiding this comment.
[Bug] (blocking) Removing pre_archive_abstracts here is a breaking API change, not an internal cleanup. The OpenClaw plugin type still requires it, the CLI renderer still expects it, the docs still publish it, and API/session tests still assert that it exists. CI is already failing in scenarios/sessions/test_session_commit.py for this exact reason. If the intent is to retire archive-index support, that needs a coordinated migration; otherwise this field needs to remain in the response.
| // 格式: "System: [时间] Compacted ... Context ... [时间] 实际内容" | ||
| if (COMPACTED_SYSTEM_MSG_RE.test(text)) { | ||
| // 提取最后一个 ] 之后的内容(即实际用户输入) | ||
| const match = text.match(/\]\s*(.+)$/); |
There was a problem hiding this comment.
[Bug] (blocking) The implementation does not match the comment here. text.match(/\]\s*(.+)$/) matches from the first ], not the last one, so an input like System: [t1] Compacted ... [t2] real content becomes Compacted ... [t2] real content instead of just real content. That writes system noise back into the session and pollutes downstream extraction.
Description
Related Issue
Type of Change
Changes Made
Testing
Checklist
Screenshots (if applicable)
Additional Notes