mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(memory): rebuild agent on workspace file change so memory edits apply
This commit is contained in:
parent
a27084f9cf
commit
ceb4da642b
@ -215,6 +215,20 @@ public class AgentService {
|
||||
agentInstances.remove(agentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the cached agent instance whenever one of its workspace files
|
||||
* changes. The system prompt (which embeds MEMORY.md / PROFILE.md / structured
|
||||
* memory) is baked into the cached instance at build time, so memory edits made
|
||||
* via tools, consolidation, or cleanup would otherwise stay invisible until an
|
||||
* agent config change or restart. Rebuilding on the next turn picks them up.
|
||||
*/
|
||||
@org.springframework.context.event.EventListener
|
||||
public void onWorkspaceFileChanged(vip.mate.workspace.document.event.WorkspaceFileChangedEvent event) {
|
||||
if (event.agentId() != null) {
|
||||
agentInstances.remove(event.agentId());
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 运行时入口 ====================
|
||||
|
||||
public String chat(Long agentId, String message, String conversationId) {
|
||||
|
||||
@ -3,8 +3,10 @@ package vip.mate.workspace.document;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import vip.mate.workspace.document.event.WorkspaceFileChangedEvent;
|
||||
import vip.mate.workspace.document.model.WorkspaceFileEntity;
|
||||
import vip.mate.workspace.document.repository.WorkspaceFileMapper;
|
||||
|
||||
@ -31,6 +33,7 @@ import java.util.stream.Collectors;
|
||||
public class WorkspaceFileService {
|
||||
|
||||
private final WorkspaceFileMapper fileMapper;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
/**
|
||||
* 列出 Agent 的所有工作区文件(按排序 + 文件名排列)
|
||||
@ -68,6 +71,7 @@ public class WorkspaceFileService {
|
||||
existing.setContent(content);
|
||||
existing.setFileSize(size);
|
||||
fileMapper.updateById(existing);
|
||||
eventPublisher.publishEvent(new WorkspaceFileChangedEvent(agentId, filename));
|
||||
return existing;
|
||||
} else {
|
||||
WorkspaceFileEntity entity = new WorkspaceFileEntity();
|
||||
@ -78,6 +82,7 @@ public class WorkspaceFileService {
|
||||
entity.setEnabled(false);
|
||||
entity.setSortOrder(0);
|
||||
fileMapper.insert(entity);
|
||||
eventPublisher.publishEvent(new WorkspaceFileChangedEvent(agentId, filename));
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@ -91,6 +96,7 @@ public class WorkspaceFileService {
|
||||
new LambdaQueryWrapper<WorkspaceFileEntity>()
|
||||
.eq(WorkspaceFileEntity::getAgentId, agentId)
|
||||
.eq(WorkspaceFileEntity::getFilename, filename));
|
||||
eventPublisher.publishEvent(new WorkspaceFileChangedEvent(agentId, filename));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package vip.mate.workspace.document.event;
|
||||
|
||||
/**
|
||||
* Published whenever an agent's workspace file is created, updated, or deleted.
|
||||
* <p>
|
||||
* Workspace files (AGENTS.md, SOUL.md, PROFILE.md, MEMORY.md, structured/*.md)
|
||||
* are baked into the agent's system prompt when its runtime instance is built.
|
||||
* Listeners use this to invalidate the cached agent instance so memory edits
|
||||
* (tool writes, consolidation, cleanup) take effect on the next turn instead of
|
||||
* only after an agent config change or restart.
|
||||
*
|
||||
* @param agentId the affected agent
|
||||
* @param filename the workspace file that changed
|
||||
*/
|
||||
public record WorkspaceFileChangedEvent(Long agentId, String filename) {
|
||||
}
|
||||
@ -38,6 +38,7 @@ import static org.mockito.Mockito.when;
|
||||
class WorkspaceMemorySearchTest {
|
||||
|
||||
@Mock private WorkspaceFileMapper fileMapper;
|
||||
@Mock private org.springframework.context.ApplicationEventPublisher eventPublisher;
|
||||
private WorkspaceFileService service;
|
||||
|
||||
@BeforeAll
|
||||
@ -51,7 +52,21 @@ class WorkspaceMemorySearchTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new WorkspaceFileService(fileMapper);
|
||||
service = new WorkspaceFileService(fileMapper, eventPublisher);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("saveFile publishes a change event so the cached agent instance is invalidated")
|
||||
void saveFilePublishesChangeEvent() {
|
||||
when(fileMapper.selectOne(any())).thenReturn(null); // new file path
|
||||
|
||||
service.saveFile(1000000001L, "MEMORY.md", "## 稳定事实\n- 用户语言:简体中文");
|
||||
|
||||
ArgumentCaptor<vip.mate.workspace.document.event.WorkspaceFileChangedEvent> captor =
|
||||
ArgumentCaptor.forClass(vip.mate.workspace.document.event.WorkspaceFileChangedEvent.class);
|
||||
org.mockito.Mockito.verify(eventPublisher).publishEvent(captor.capture());
|
||||
assertThat(captor.getValue().agentId()).isEqualTo(1000000001L);
|
||||
assertThat(captor.getValue().filename()).isEqualTo("MEMORY.md");
|
||||
}
|
||||
|
||||
// ---------- tokenize ----------
|
||||
|
||||
Loading…
Reference in New Issue
Block a user