mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(agent): hide disabled agents from the chat picker and reject chat calls against them (#105)
This commit is contained in:
parent
1bfb5f7fc8
commit
691d2b867b
@ -65,9 +65,26 @@ public class AgentService {
|
||||
* 按工作区列出 Agent
|
||||
*/
|
||||
public List<AgentEntity> listAgentsByWorkspace(Long workspaceId) {
|
||||
return agentMapper.selectList(new LambdaQueryWrapper<AgentEntity>()
|
||||
.eq(AgentEntity::getWorkspaceId, workspaceId)
|
||||
.orderByDesc(AgentEntity::getCreateTime));
|
||||
return listAgentsByWorkspace(workspaceId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按工作区列出 Agent,可选过滤启用状态。
|
||||
*
|
||||
* @param enabled non-null restricts the result set to agents whose
|
||||
* {@code enabled} column matches the given value.
|
||||
* Pass {@code true} from chat selectors so disabled
|
||||
* agents disappear from the picker; the admin
|
||||
* management page passes {@code null} to keep
|
||||
* disabled rows visible for re-enabling.
|
||||
*/
|
||||
public List<AgentEntity> listAgentsByWorkspace(Long workspaceId, Boolean enabled) {
|
||||
LambdaQueryWrapper<AgentEntity> q = new LambdaQueryWrapper<AgentEntity>()
|
||||
.eq(AgentEntity::getWorkspaceId, workspaceId);
|
||||
if (enabled != null) {
|
||||
q.eq(AgentEntity::getEnabled, enabled);
|
||||
}
|
||||
return agentMapper.selectList(q.orderByDesc(AgentEntity::getCreateTime));
|
||||
}
|
||||
|
||||
public AgentEntity getAgent(Long id) {
|
||||
|
||||
@ -55,10 +55,13 @@ public class AgentController {
|
||||
@GetMapping
|
||||
@RequireWorkspaceRole("viewer")
|
||||
public R<List<AgentEntity>> list(
|
||||
@RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId) {
|
||||
@RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId,
|
||||
@RequestParam(value = "enabled", required = false) Boolean enabled) {
|
||||
// 无 header 时强制使用默认 workspace,不返回全局数据
|
||||
long wsId = workspaceId != null ? workspaceId : 1L;
|
||||
return R.ok(agentService.listAgentsByWorkspace(wsId));
|
||||
// enabled=true: chat selectors hide disabled agents.
|
||||
// enabled=null: admin management page sees enabled + disabled.
|
||||
return R.ok(agentService.listAgentsByWorkspace(wsId, enabled));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取Agent详情")
|
||||
@ -187,6 +190,7 @@ public class AgentController {
|
||||
@RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId) {
|
||||
AgentEntity agent = agentService.getAgent(id);
|
||||
verifyResourceWorkspace(agent != null ? agent.getWorkspaceId() : null, workspaceId);
|
||||
verifyAgentEnabled(agent);
|
||||
|
||||
// RFC-058 PR-1: Utf8SseEmitter 显式 charset=UTF-8,防止中文 SSE 乱码
|
||||
SseEmitter emitter = new Utf8SseEmitter(5 * 60 * 1000L);
|
||||
@ -226,6 +230,7 @@ public class AgentController {
|
||||
@RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId) {
|
||||
AgentEntity agent = agentService.getAgent(id);
|
||||
verifyResourceWorkspace(agent != null ? agent.getWorkspaceId() : null, workspaceId);
|
||||
verifyAgentEnabled(agent);
|
||||
return R.ok(agentService.chat(id, request.getMessage(), request.getConversationId()));
|
||||
}
|
||||
|
||||
@ -238,6 +243,7 @@ public class AgentController {
|
||||
@RequestHeader(value = "X-Workspace-Id", required = false) Long workspaceId) {
|
||||
AgentEntity agent = agentService.getAgent(id);
|
||||
verifyResourceWorkspace(agent != null ? agent.getWorkspaceId() : null, workspaceId);
|
||||
verifyAgentEnabled(agent);
|
||||
return R.ok(agentService.execute(id, request.getMessage(), request.getConversationId()));
|
||||
}
|
||||
|
||||
@ -268,6 +274,21 @@ public class AgentController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block runtime calls against an agent flagged as disabled.
|
||||
*
|
||||
* <p>{@code AgentService#getOrBuildAgent} also checks the flag, but only on
|
||||
* a cache miss — once the {@code BaseAgent} instance is warm, a flip to
|
||||
* disabled would silently keep serving requests until something else
|
||||
* invalidates the cache. Enforcing here at the controller closes that gap
|
||||
* for every external entry point.
|
||||
*/
|
||||
private void verifyAgentEnabled(AgentEntity agent) {
|
||||
if (agent != null && !Boolean.TRUE.equals(agent.getEnabled())) {
|
||||
throw new MateClawException("err.agent.disabled", "Agent 已禁用: " + agent.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private Long resolveUserId(Authentication auth) {
|
||||
if (auth == null) {
|
||||
throw new MateClawException("err.auth.unauthenticated", 401, "Not authenticated");
|
||||
|
||||
@ -93,7 +93,12 @@ export const authApi = {
|
||||
|
||||
// ==================== Agent ====================
|
||||
export const agentApi = {
|
||||
list: () => http.get('/agents'),
|
||||
/**
|
||||
* @param params.enabled when `true`, restricts the result to enabled agents
|
||||
* (used by chat selectors so disabled agents disappear from the picker).
|
||||
* Omit to receive enabled + disabled (admin management page).
|
||||
*/
|
||||
list: (params?: { enabled?: boolean }) => http.get('/agents', { params }),
|
||||
get: (id: string | number) => http.get(`/agents/${id}`),
|
||||
create: (data: any) => http.post('/agents', data),
|
||||
update: (id: string | number, data: any) => http.put(`/agents/${id}`, data),
|
||||
|
||||
@ -1163,7 +1163,10 @@ watch(selectedAgentId, async (id) => {
|
||||
// ============ 方法 ============
|
||||
async function loadAgents() {
|
||||
try {
|
||||
const res: any = await agentApi.list()
|
||||
// Hide disabled agents from the picker — they cannot be chatted with
|
||||
// (the chat endpoints reject disabled agents), so showing them invites
|
||||
// a confusing failure path. The admin Agents view passes no filter.
|
||||
const res: any = await agentApi.list({ enabled: true })
|
||||
agents.value = res.data || []
|
||||
// 只有在 URL 没有指定 agentId 且当前无选中时,才默认选第一个
|
||||
if (agents.value.length > 0 && !selectedAgentId.value && !route.query.agentId) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user