package vip.mate.skill.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import vip.mate.common.result.R;
import vip.mate.agent.AgentService;
import vip.mate.agent.binding.model.AgentSkillBinding;
import vip.mate.agent.binding.repository.AgentSkillBindingMapper;
import vip.mate.agent.binding.service.AgentBindingService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import vip.mate.agent.model.AgentEntity;
import vip.mate.skill.lessons.SkillLessonsService;
import vip.mate.skill.manifest.SkillManifest;
import vip.mate.skill.model.SkillEntity;
import vip.mate.skill.runtime.SkillDependencyChecker;
import vip.mate.skill.runtime.SkillCatalogSort;
import vip.mate.skill.runtime.SkillCatalogSorter;
import vip.mate.skill.service.SkillService;
import vip.mate.skill.synthesis.SkillSynthesisService;
import vip.mate.skill.runtime.SkillRuntimeService;
import vip.mate.skill.runtime.model.ResolvedSkill;
import vip.mate.skill.workspace.BundledSkillSyncer;
import vip.mate.skill.workspace.SkillFileSyncer;
import vip.mate.skill.workspace.SkillWorkspaceManager;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 技能管理接口
*
* 提供技能的 CRUD、启用/禁用、按类型查询、技能摘要等能力。
* 对应前端 SkillMarket 页面。
*
* @author MateClaw Team
*/
@Tag(name = "技能管理")
@RestController
@RequestMapping("/api/v1/skills")
@RequiredArgsConstructor
public class SkillController {
private final SkillService skillService;
private final SkillRuntimeService skillRuntimeService;
private final SkillWorkspaceManager workspaceManager;
private final BundledSkillSyncer bundledSkillSyncer;
private final SkillFileSyncer skillFileSyncer;
private final SkillSynthesisService synthesisService;
private final SkillDependencyChecker dependencyChecker;
private final SkillLessonsService lessonsService;
private final AgentSkillBindingMapper agentSkillBindingMapper;
private final AgentService agentService;
private final AgentBindingService agentBindingService;
private final vip.mate.skill.mcp.McpSkillBridge mcpSkillBridge;
private final vip.mate.skill.acp.AcpSkillBridge acpSkillBridge;
@Operation(summary = "获取技能分页列表(RFC-042 §2.1)")
@GetMapping
public R> list(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(required = false) String keyword,
@RequestParam(required = false) String skillType,
@RequestParam(required = false) Boolean enabled,
@RequestParam(required = false) String scanStatus,
@RequestParam(required = false) String sort,
@RequestParam(required = false) String source,
@RequestParam(required = false) String runtime,
@RequestParam(required = false) Long agentId) {
Set pinnedSkillIds = agentId != null ? agentBindingService.getBoundSkillIds(agentId) : Set.of();
if (pinnedSkillIds == null) pinnedSkillIds = Set.of();
IPage dbPage = skillService.pageSkills(
page, size, keyword, skillType, enabled, scanStatus, sort, source, runtime, pinnedSkillIds);
List virtualSkills = visibleVirtualSkills(
keyword, skillType, enabled, scanStatus, sort, source, runtime);
if (!virtualSkills.isEmpty()) {
VirtualPageMergeResult merged = mergeVirtualTailPageRecords(
dbPage.getRecords(), virtualSkills, dbPage.getTotal(), page, size);
dbPage.setRecords(merged.records());
dbPage.setTotal(merged.total());
}
return R.ok(dbPage);
}
@Operation(summary = "获取各类型技能计数(tab 徽章用)")
@GetMapping("/counts")
public R