fix(memory): HiL edit validates key exists in MEMORY.md sections

This commit is contained in:
matevip 2026-04-21 17:34:22 +08:00
parent e69aa2be04
commit be9dfdf727
2 changed files with 17 additions and 2 deletions

View File

@ -129,7 +129,7 @@ public class DreamController {
@PathVariable Long reportId,
@PathVariable String key,
@RequestBody Map<String, String> body) {
// P2-5: Validate reportId belongs to this agent (0 = direct edit, skip validation)
// Validate reportId belongs to this agent (0 = direct edit from MemoryBrowser)
if (reportId != 0L) {
DreamReportEntity report = dreamReportMapper.selectOne(
new LambdaQueryWrapper<DreamReportEntity>()
@ -140,11 +140,16 @@ public class DreamController {
return R.fail("Report not found or does not belong to this agent");
}
}
// Validate key is an existing section in MEMORY.md (prevent arbitrary edits)
String decodedKey = java.net.URLDecoder.decode(key, java.nio.charset.StandardCharsets.UTF_8);
if (!hilService.sectionExists(agentId, decodedKey)) {
return R.fail("Section '" + decodedKey + "' not found in MEMORY.md");
}
String newContent = body.get("content");
if (newContent == null || newContent.isBlank()) {
return R.fail("content is required");
}
hilService.editMemoryEntry(agentId, key, newContent);
hilService.editMemoryEntry(agentId, decodedKey, newContent);
return R.ok(null);
}

View File

@ -64,4 +64,14 @@ public class MemoryHilService {
eventPublisher.publishEvent(new MemoryWriteEvent(agentId, "MEMORY.md", "user-edit", newContent));
log.info("[HiL] User edited MEMORY.md section '{}' for agent={}", key, agentId);
}
/**
* Check if a section heading exists in MEMORY.md.
* Used by DreamController to validate edit key before allowing write.
*/
public boolean sectionExists(Long agentId, String key) {
WorkspaceFileEntity file = workspaceFileService.getFile(agentId, "MEMORY.md");
if (file == null || file.getContent() == null) return false;
return file.getContent().contains("## " + key);
}
}