package com.xly.web; import com.xly.agent.AgentIdentity; import com.xly.service.AuthzService; import com.xly.service.ConversationService; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; import java.util.List; import java.util.Map; /** * 会话管理 REST —— 支撑前端的「多命名会话」侧栏(列表 / 新建 / 删除 / 历史)。 * *

身份:一律由 {@code Authorization} 头经 {@link AuthzService#resolveIdentity} 服务端内省得出, * 不接受客户端自报的 userid;会话 id 绑定用户命名空间,越权访问他人会话直接 403。 */ @RestController @RequestMapping("/api/agent/conversations") public class ConversationController { private final ConversationService conversations; private final AuthzService authz; public ConversationController(ConversationService conversations, AuthzService authz) { this.conversations = conversations; this.authz = authz; } /** 列出当前登录用户的会话(最近更新在前)。 */ @GetMapping public List> list(@RequestHeader(value = "Authorization", required = false) String auth) { return conversations.list(identity(auth).userId()); } /** 新建空会话,返回 conversationId。 */ @PostMapping public Map create(@RequestHeader(value = "Authorization", required = false) String auth) { return Map.of("conversationId", conversations.create(identity(auth).userId())); } /** 删除自己的会话(含消息记忆、账本、状态槽)。 */ @DeleteMapping("/{convId}") public Map delete(@PathVariable("convId") String convId, @RequestHeader(value = "Authorization", required = false) String auth) { String uid = requireOwner(auth, convId); conversations.delete(uid, convId); return Map.of("ok", true); } /** 自己会话的历史消息(用于切换会话时回填)。 */ @GetMapping("/{convId}/messages") public List> messages(@PathVariable("convId") String convId, @RequestHeader(value = "Authorization", required = false) String auth) { requireOwner(auth, convId); return conversations.history(convId); } private AgentIdentity identity(String auth) { AgentIdentity id = authz.resolveIdentity(auth); if (id == null) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "登录已过期或未登录"); } return id; } private String requireOwner(String auth, String convId) { AgentIdentity id = identity(auth); if (!conversations.owns(id.userId(), convId)) { throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权访问该会话"); } return id.userId(); } }