package com.xly.agent; import java.util.Set; /** * 单次 agent 调用的「按调用上下文」身份(架构 §5/§7 的 per-call context)。 * *

由 {@code AgentChatController} 从前端请求解析(透传的 ERP 登录 token + 稳定身份),随 * {@link com.xly.config.AgentFactory} 注入到**每请求新建**的工具实例里——因为 LangChain4j 流式 * 工具执行发生在模型 HTTP 回调线程而非控制器工作线程,ThreadLocal 不可靠,只能把身份放进工具实例本身。 * *

{@link #token} = 透传的用户 ERP 会话 token(可空 → 退回 dev-login)。{@link #grantedModuleIds} * = 该用户实际有权的表单/菜单 id 集合({@code null} = 管理员/全部),Read/Query/Write 共用此边界。 * token 绝不进 prompt / LLM 可见文本。 */ public final class AgentIdentity { private final String token; private final String userId; private final String userNo; private final String brandsId; private final String subsidiaryId; private final String userType; private final Set grantedModuleIds; // null = 全部(管理员) public AgentIdentity(String token, String userId, String userNo, String brandsId, String subsidiaryId, String userType, Set grantedModuleIds) { this.token = token; this.userId = userId; this.userNo = userNo; this.brandsId = brandsId; this.subsidiaryId = subsidiaryId; this.userType = userType; this.grantedModuleIds = grantedModuleIds; } /** 透传的用户 token;为空表示回退到 dev-login(本地开发)。 */ public String token() { return token; } public boolean hasUserToken() { return token != null && !token.isBlank(); } public String userId() { return userId; } public String userNo() { return userNo; } public String brandsId() { return brandsId; } public String subsidiaryId() { return subsidiaryId; } public String userType() { return userType; } /** null = 全部权限(管理员)。 */ public Set grantedModuleIds() { return grantedModuleIds; } public boolean isAdminAll() { return grantedModuleIds == null; } public boolean canAccessModule(String moduleId) { return grantedModuleIds == null || (moduleId != null && grantedModuleIds.contains(moduleId)); } }