mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 19:23:42 +08:00
feat(skill-mcp): expose readable display name alongside prefixed MCP tool names
Add a parallel effectiveAllowedToolsDisplay field on the runtime status payload so the SkillMarket detail drawer can render mcp_<server>_<slug>_<hash> with the raw tool name appended in parentheses, while leaving the original prefixed list unchanged for any caller that needs the machine name. McpSkillBridge#decorateToolNameForDisplay reverses a prefixed name via the per-server cached tool list; the frontend prefers the new display field and falls back to effectiveAllowedTools when the field is absent.
This commit is contained in:
parent
adddf0402a
commit
18148aa724
@ -1,6 +1,8 @@
|
||||
package vip.mate.skill.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -57,6 +59,7 @@ public class SkillController {
|
||||
private final AgentBindingService agentBindingService;
|
||||
private final vip.mate.skill.mcp.McpSkillBridge mcpSkillBridge;
|
||||
private final vip.mate.skill.acp.AcpSkillBridge acpSkillBridge;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Operation(summary = "获取技能分页列表(RFC-042 §2.1)")
|
||||
@GetMapping
|
||||
@ -392,8 +395,34 @@ public class SkillController {
|
||||
|
||||
@Operation(summary = "获取所有技能的运行时解析状态(管理页面使用)")
|
||||
@GetMapping("/runtime/status")
|
||||
public R<List<ResolvedSkill>> getRuntimeStatus() {
|
||||
return R.ok(skillRuntimeService.resolveAllSkillsStatus());
|
||||
public R<List<Map<String, Object>>> getRuntimeStatus() {
|
||||
List<ResolvedSkill> skills = skillRuntimeService.resolveAllSkillsStatus();
|
||||
return R.ok(skills.stream().map(this::toRuntimeStatusView).toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a display transformation on `effectiveAllowedTools` (returned to the frontend),
|
||||
* and store the transformed result in `effectiveAllowedToolsDisplay`.
|
||||
* In addition to displaying the tool name in the format `mcp_<serverId>_<slug>_<hash6>`,
|
||||
* also display the original MCP tool name in parentheses immediately following it.
|
||||
*
|
||||
* @param skill
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> toRuntimeStatusView(ResolvedSkill skill) {
|
||||
Map<String, Object> view = objectMapper.convertValue(
|
||||
skill,
|
||||
new TypeReference<Map<String, Object>>() {}
|
||||
);
|
||||
|
||||
if ("mcp".equalsIgnoreCase(skill.getSource())) {
|
||||
List<String> displayTools = skill.getEffectiveAllowedTools().stream()
|
||||
.map(mcpSkillBridge::decorateToolNameForDisplay)
|
||||
.toList();
|
||||
view.put("effectiveAllowedToolsDisplay", displayTools);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Operation(summary = "刷新 active skills 缓存,resync=true 时同步内置技能到 workspace")
|
||||
|
||||
@ -121,6 +121,26 @@ public class McpSkillBridge {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "display-only" method to reverse-lookup a prefixed name back to its raw name.
|
||||
*
|
||||
* @param prefixedName
|
||||
* @return
|
||||
*/
|
||||
public String decorateToolNameForDisplay(String prefixedName) {
|
||||
McpToolNameResolver.ParsedRef ref = McpToolNameResolver.parse(prefixedName);
|
||||
if (ref == null) return prefixedName;
|
||||
|
||||
McpServerEntity server = mcpServerService.getById(ref.serverId());
|
||||
for (String raw : readToolRawNames(server)) {
|
||||
String rebuilt = McpToolNameResolver.prefixedName(ref.serverId(), raw);
|
||||
if (rebuilt.equals(prefixedName)) {
|
||||
return prefixedName + " (" + raw + ")";
|
||||
}
|
||||
}
|
||||
return prefixedName;
|
||||
}
|
||||
|
||||
private List<McpServerEntity> listEnabledServers() {
|
||||
try {
|
||||
return mcpServerService.listEnabled();
|
||||
|
||||
@ -311,6 +311,8 @@ export interface SkillRuntimeStatus {
|
||||
activeFeatures?: string[]
|
||||
/** Tools advertised to the LLM after feature filtering */
|
||||
effectiveAllowedTools?: string[]
|
||||
/** Human-readable tool names for display after feature filtering */
|
||||
effectiveAllowedToolsDisplay?: string[]
|
||||
}
|
||||
|
||||
/** RFC-090 §14.6 — typed view onto manifest_json */
|
||||
|
||||
@ -807,7 +807,9 @@ const detailManifest = computed(() => detailRuntime.value?.manifest ?? null)
|
||||
const detailManifestPretty = computed(() =>
|
||||
detailManifest.value ? JSON.stringify(detailManifest.value, null, 2) : '',
|
||||
)
|
||||
const detailEffectiveTools = computed(() => detailRuntime.value?.effectiveAllowedTools || [])
|
||||
const detailEffectiveTools = computed(() =>
|
||||
detailRuntime.value?.effectiveAllowedToolsDisplay || detailRuntime.value?.effectiveAllowedTools || [],
|
||||
)
|
||||
const detailToolsCount = computed(() => detailEffectiveTools.value.length)
|
||||
const detailFeatures = computed(() => {
|
||||
const m = detailManifest.value
|
||||
|
||||
Loading…
Reference in New Issue
Block a user