mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 19:23:42 +08:00
- Reconcile approval status atomically: DB row, message metadata, in-memory store - Approve and deny both flip the tool-call card + timeline segment to a terminal state on the gate message — no more orange spinner stuck after a decision - Frontend hydrate matches by pendingId and reverse-converges to expired so a refresh after server-side timeout / consume clears the banner without restart - Stop sweep, GC timeout, and JVM restart all close the loop with consistent state - Remove the dead REST /approve endpoint + matching frontend client export so there is only one resolve path to maintain
63 lines
2.1 KiB
Java
63 lines
2.1 KiB
Java
package vip.mate.approval;
|
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import vip.mate.common.result.R;
|
|
import vip.mate.workspace.conversation.ConversationService;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Approval read-only endpoints.
|
|
* <p>
|
|
* Web approve / deny actions ride the SSE {@code POST /chat/stream} path with
|
|
* {@code /approve} or {@code /deny} text commands ({@link vip.mate.channel.web.ChatController}
|
|
* intercepts), so a write-style {@code POST /approve} REST endpoint was deleted
|
|
* in RFC-067 PR 6 — it bypassed the unified workflow lifecycle and let any
|
|
* future caller silently regress to the pre-RFC ghost-approval state.
|
|
* <p>
|
|
* Only {@link #getPendingApprovals} remains, used by the frontend for hydration
|
|
* after page refresh.
|
|
*
|
|
* @author MateClaw Team
|
|
*/
|
|
@Tag(name = "工具审批")
|
|
@Slf4j
|
|
@RestController
|
|
@RequestMapping("/api/v1/chat")
|
|
@RequiredArgsConstructor
|
|
public class ApprovalController {
|
|
|
|
private final ApprovalWorkflowService approvalService;
|
|
private final ConversationService conversationService;
|
|
|
|
/**
|
|
* Hydration query for page refresh: returns every pending approval still
|
|
* waiting in the conversation. The frontend uses this to rebuild the
|
|
* approval banner after a reload.
|
|
*/
|
|
@Operation(summary = "查询待审批记录")
|
|
@GetMapping("/{conversationId}/pending-approvals")
|
|
public R<List<Map<String, Object>>> getPendingApprovals(
|
|
@PathVariable String conversationId,
|
|
Authentication auth) {
|
|
|
|
if (auth == null) {
|
|
return R.fail(401, "未登录,请先登录");
|
|
}
|
|
String username = auth.getName();
|
|
|
|
if (!conversationService.isConversationOwner(conversationId, username)) {
|
|
return R.fail(403, "无权访问该会话");
|
|
}
|
|
|
|
List<Map<String, Object>> pending = approvalService.getPendingByConversation(conversationId);
|
|
return R.ok(pending);
|
|
}
|
|
}
|