diff --git a/mateclaw-server/src/main/java/vip/mate/workspace/conversation/ConversationService.java b/mateclaw-server/src/main/java/vip/mate/workspace/conversation/ConversationService.java index 4fc8106a..1790e4c5 100644 --- a/mateclaw-server/src/main/java/vip/mate/workspace/conversation/ConversationService.java +++ b/mateclaw-server/src/main/java/vip/mate/workspace/conversation/ConversationService.java @@ -45,7 +45,13 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * 会话管理服务 + * Conversation management service (会话管理服务). + * + *
Owns the full lifecycle of {@link ConversationEntity} and + * {@link MessageEntity} rows — list / get-or-create / save / rename / + * pin / delete / compress / approval-state reconciliation — and the + * cascade of side-tables that hang off a conversation (approvals, + * async tasks, channel sessions, attachment files, tool-result spill). * * @author MateClaw Team */ @@ -79,18 +85,27 @@ public class ConversationService { } /** - * 获取用户的会话列表(返回 VO,包含 agentName/agentIcon/status) + * List conversations for a user, returned as VOs that include + * {@code agentName} / {@code agentIcon} / {@code status}. + * + *
获取用户的会话列表(返回 VO,包含 agentName / agentIcon / status)。
*/
public List 获取用户的会话列表(按工作区过滤)。
*/
public List 获取或创建会话(向后兼容,默认 workspace 1)。
*/
@Transactional
public ConversationEntity getOrCreateConversation(String conversationId, Long agentId, String username) {
@@ -139,7 +158,9 @@ public class ConversationService {
}
/**
- * 获取或创建会话(workspace 感知)
+ * Workspace-aware get-or-create.
+ *
+ * 获取或创建会话(workspace 感知)。
*/
@Transactional
public ConversationEntity getOrCreateConversation(String conversationId, Long agentId,
@@ -163,7 +184,10 @@ public class ConversationService {
}
/**
- * 创建子会话(委派场景),关联父会话 ID。
+ * Create a child conversation (delegation scenario), linking it back to
+ * its parent via {@code parentConversationId}.
+ *
+ * 创建子会话(委派场景),关联父会话 ID。
*/
@Transactional
public ConversationEntity createChildConversation(String childConversationId, Long agentId,
@@ -177,11 +201,19 @@ public class ConversationService {
}
/**
- * 获取或创建共享渠道会话。
- *
- * IM 渠道(飞书/钉钉/企微等)的会话需要在控制台中对登录用户可见,
- * 因此统一使用 system 作为 owner。对于历史上已写成发送者昵称/open_id 的会话,
- * 这里会自动修正为 system,避免控制台列表和消息接口因权限校验而不可见。
+ * Get-or-create a shared channel conversation.
+ *
+ * IM-channel (Feishu / DingTalk / WeCom / …) conversations must be
+ * visible to every logged-in user in the admin console, so the owner is
+ * uniformly set to {@code system}. For legacy rows whose owner was
+ * historically written as a sender nickname / {@code open_id}, this
+ * method silently rewrites it to {@code system} on read — otherwise the
+ * console list and message endpoints would 403 those rows.
+ *
+ * 获取或创建共享渠道会话。IM 渠道(飞书 / 钉钉 / 企微等)的会话需要在控制台中
+ * 对登录用户可见,因此统一使用 {@code system} 作为 owner。对于历史上已写成发送者
+ * 昵称 / open_id 的会话,这里会自动修正为 {@code system},避免控制台列表和
+ * 消息接口因权限校验而不可见。
*/
@Transactional
public ConversationEntity getOrCreateSharedConversation(String conversationId, Long agentId) {
@@ -189,11 +221,14 @@ public class ConversationService {
}
/**
- * 获取或创建共享渠道会话(workspace 感知)。
+ * Workspace-aware get-or-create for shared channel conversations.
*
* Delegates to the 5-arg overload with {@code null} model defaults —
* preserves the legacy behavior for any caller that doesn't have an
* agent-level model to inherit from.
+ *
+ * 获取或创建共享渠道会话(workspace 感知)。委托到 5 参重载,model 默认值传
+ * {@code null},保留对不需要继承 agent 模型的调用方的旧行为。
*/
@Transactional
public ConversationEntity getOrCreateSharedConversation(String conversationId, Long agentId, Long workspaceId) {
@@ -245,13 +280,14 @@ public class ConversationService {
try {
conversationMapper.insert(conv);
} catch (org.springframework.dao.DuplicateKeyException e) {
- // 并发插入:另一个线程已创建,回退到查询
+ // Concurrent insert: another thread won the race — re-query
+ // and fall through to the owner-correction block below.
+ // 并发插入:另一个线程已创建,回退到查询;继续走下面的 owner 修正逻辑。
conv = conversationMapper.selectOne(new LambdaQueryWrapper 保存消息并更新会话统计。
*/
@Transactional
public MessageEntity saveMessage(String conversationId, String role, String content) {
@@ -327,21 +366,26 @@ public class ConversationService {
message.setCompletionTokens(completionTokens);
message.setRuntimeModel(runtimeModel);
message.setRuntimeProvider(runtimeProvider);
- message.setMetadata(metadata != null ? metadata : "{}"); // 初始化为空对象
+ message.setMetadata(metadata != null ? metadata : "{}"); // Initialize as empty JSON object / 初始化为空对象
messageMapper.insert(message);
- // 更新会话信息
+ // Update aggregate counters on the parent conversation row.
+ // 更新会话信息(消息计数、最后活跃时间、最后一条摘要)。
ConversationEntity conv = conversationMapper.selectOne(new LambdaQueryWrapper 更新消息的元数据(toolCalls / plan / currentPhase 等)。
*/
@Transactional
public void updateMessageMetadata(Long messageId, String metadata) {
@@ -362,7 +408,9 @@ public class ConversationService {
}
/**
- * 重命名会话
+ * Rename a conversation.
+ *
+ * 重命名会话。
*/
@Transactional
public void renameConversation(String conversationId, String title) {
@@ -388,7 +436,9 @@ public class ConversationService {
}
/**
- * 更新会话的流状态(running / idle)
+ * Update a conversation's stream status ({@code running} / {@code idle}).
+ *
+ * 更新会话的流状态(running / idle)。
*/
@Transactional
public void updateStreamStatus(String conversationId, String streamStatus) {
@@ -451,7 +501,10 @@ public class ConversationService {
}
/**
- * 获取会话最后一条消息内容(用于 rate limit 防护等场景)
+ * Get the latest message preview text for a conversation — used by
+ * rate-limit guards and similar duplicate-detection paths.
+ *
+ * 获取会话最后一条消息内容(用于 rate limit 防护等场景)。
*/
public String getLastMessage(String conversationId) {
ConversationEntity conv = conversationMapper.selectOne(new LambdaQueryWrapper 获取会话的消息数量。
*/
public int getMessageCount(String conversationId) {
ConversationEntity conv = conversationMapper.selectOne(new LambdaQueryWrapper 获取会话的消息历史。
*/
public List 加载最近 N 条消息(倒序取出后翻转为正序);利用复合索引
+ * {@code (conversation_id, create_time)} 高效分页。
*/
public List 分页加载指定 ID 之前的消息(用于前端上拉加载更早消息);
* 返回倒序结果,调用方需自行 reverse。
*/
public List 查询会话消息总数。
*/
public long countMessages(String conversationId) {
return messageMapper.selectCount(
@@ -748,7 +815,10 @@ public class ConversationService {
}
/**
- * 清空会话消息(同时清理附件文件)
+ * Wipe all messages in a conversation and reset its aggregate counters,
+ * also cleaning any attachment files those messages produced.
+ *
+ * 清空会话消息(同时清理附件文件)。
*/
@Transactional
public void clearMessages(String conversationId) {
@@ -898,9 +968,13 @@ public class ConversationService {
}
/**
- * 删除指定会话中所有审批占位 assistant 消息
- *
- * 在 replay 前调用,确保 LLM 上下文中不包含任何审批相关文本。
+ * Remove all approval-placeholder assistant messages from a conversation.
+ *
+ * Called before replay so the LLM context contains no approval-related
+ * stub text that could confuse the next turn.
+ *
+ * 删除指定会话中所有审批占位 assistant 消息。在 replay 前调用,
+ * 确保 LLM 上下文中不包含任何审批相关文本。
*/
/**
* Reconcile persisted assistant-message state when one or more pending approvals
@@ -1124,7 +1198,9 @@ public class ConversationService {
}
/**
- * 检查会话是否存在
+ * Check whether a conversation row exists.
+ *
+ * 检查会话是否存在。
*/
public boolean conversationExists(String conversationId) {
return conversationMapper.selectCount(
@@ -1133,8 +1209,12 @@ public class ConversationService {
}
/**
- * 校验用户是否拥有该会话。
- * 定时任务产生的会话(username=system)对所有登录用户可见。
+ * Check whether a user owns the conversation, treating system-owned
+ * rows (e.g. from scheduled jobs / IM channels) as visible to every
+ * authenticated user.
+ *
+ * 校验用户是否拥有该会话。定时任务产生的会话(username = system)
+ * 对所有登录用户可见。
*/
public boolean isConversationOwner(String conversationId, String username) {
ConversationEntity conv = conversationMapper.selectOne(
@@ -1147,7 +1227,9 @@ public class ConversationService {
}
/**
- * 获取会话的持久化流状态
+ * Get the persisted stream status for a conversation.
+ *
+ * 获取会话的持久化流状态。
*/
public String getStreamStatus(String conversationId) {
ConversationEntity conv = conversationMapper.selectOne(