mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
feat(skill): scope skill dedup, name uniqueness and reinstall/uninstall lookup by workspace
This commit is contained in:
parent
c18ff31ae8
commit
67301c5f7c
@ -82,7 +82,10 @@ public class SkillInstaller {
|
||||
* {@code SkillService.hardDeleteSkill} via {@code DELETE /skills/{id}}.
|
||||
*/
|
||||
public void uninstall(String skillName, Long workspaceId) {
|
||||
List<SkillEntity> skills = skillService.listSkills();
|
||||
// Scope the lookup to this workspace (+ builtin) so a same-named skill in
|
||||
// another workspace is never picked up (which would wrongly 403 below even
|
||||
// though the current workspace has its own skill to uninstall).
|
||||
List<SkillEntity> skills = skillService.listSkills(workspaceId);
|
||||
SkillEntity target = skills.stream()
|
||||
.filter(s -> s.getName().equals(skillName))
|
||||
.findFirst()
|
||||
@ -147,8 +150,9 @@ public class SkillInstaller {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
// 3. 检查是否已存在
|
||||
boolean exists = skillService.listSkills().stream()
|
||||
// 3. 检查是否已存在(按工作区隔离:只在本工作区 + builtin 范围内查重,
|
||||
// 不同工作区的同名技能可以各自独立安装)
|
||||
boolean exists = skillService.listSkills(request.getWorkspaceId()).stream()
|
||||
.anyMatch(s -> s.getName().equals(skillName));
|
||||
if (exists && !Boolean.TRUE.equals(request.getOverwrite())) {
|
||||
task.markFailed("Skill '" + skillName + "' already exists. Set overwrite=true to replace.");
|
||||
@ -218,7 +222,8 @@ public class SkillInstaller {
|
||||
throw new vip.mate.exception.MateClawException("err.skill.name_required", "Cannot determine skill name from bundle");
|
||||
}
|
||||
|
||||
boolean exists = skillService.listSkills().stream()
|
||||
// Workspace-scoped dedup: same-named skills in different workspaces coexist.
|
||||
boolean exists = skillService.listSkills(workspaceId).stream()
|
||||
.anyMatch(s -> s.getName().equals(skillName));
|
||||
if (exists && !overwrite) {
|
||||
throw new vip.mate.exception.MateClawException("err.skill.name_exists",
|
||||
@ -263,7 +268,9 @@ public class SkillInstaller {
|
||||
boolean enable, Long workspaceId) {
|
||||
SkillEntity skillEntity;
|
||||
if (exists) {
|
||||
skillEntity = skillService.listSkills().stream()
|
||||
// Locate the row to update within THIS workspace (+ builtin), so a
|
||||
// reinstall never grabs a same-named skill owned by another workspace.
|
||||
skillEntity = skillService.listSkills(workspaceId).stream()
|
||||
.filter(s -> s.getName().equals(skillName))
|
||||
.findFirst().orElseThrow();
|
||||
skillEntity.setSkillContent(bundle.content());
|
||||
|
||||
@ -274,7 +274,8 @@ public class SkillService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称查找技能(RFC-023:SkillManageTool 重名检查用)
|
||||
* 按名称查找技能(全局,跨所有工作区)。仅用于内置技能同步等全局语义场景;
|
||||
* 工作区相关的重名检查请用 {@link #findByName(String, Long)}。
|
||||
*/
|
||||
public SkillEntity findByName(String name) {
|
||||
return skillMapper.selectOne(new LambdaQueryWrapper<SkillEntity>()
|
||||
@ -282,6 +283,17 @@ public class SkillService {
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称在指定工作区内查找技能(含 builtin 全局可见)。用于工作区隔离的
|
||||
* 重名/存在性检查,避免跨工作区错误命中别的工作区的同名技能。
|
||||
*/
|
||||
public SkillEntity findByName(String name, Long workspaceId) {
|
||||
LambdaQueryWrapper<SkillEntity> wrapper = new LambdaQueryWrapper<SkillEntity>()
|
||||
.eq(SkillEntity::getName, name);
|
||||
applyWorkspaceScope(wrapper, workspaceId);
|
||||
return skillMapper.selectOne(wrapper.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按类型获取技能列表
|
||||
*/
|
||||
@ -323,9 +335,12 @@ public class SkillService {
|
||||
throw new MateClawException("err.skill.name_required", "技能名称不能为空");
|
||||
}
|
||||
|
||||
// 检查名称唯一性
|
||||
Long count = skillMapper.selectCount(new LambdaQueryWrapper<SkillEntity>()
|
||||
.eq(SkillEntity::getName, skill.getName()));
|
||||
// 名称唯一性按工作区隔离:同名技能只要不在同一工作区(且都不是 builtin)即可共存。
|
||||
// 撞 builtin 名仍视为冲突(builtin 全局可见)。
|
||||
LambdaQueryWrapper<SkillEntity> dupCheck = new LambdaQueryWrapper<SkillEntity>()
|
||||
.eq(SkillEntity::getName, skill.getName());
|
||||
applyWorkspaceScope(dupCheck, skill.getWorkspaceId());
|
||||
Long count = skillMapper.selectCount(dupCheck);
|
||||
if (count > 0) {
|
||||
throw new MateClawException("err.skill.name_exists", "技能名称已存在: " + skill.getName());
|
||||
}
|
||||
|
||||
@ -95,8 +95,9 @@ public class SkillSynthesisService {
|
||||
}
|
||||
name = name.strip().toLowerCase().replaceAll("[^a-z0-9._-]", "-");
|
||||
|
||||
// 去重
|
||||
SkillEntity existing = skillService.findByName(name);
|
||||
// 去重(按工作区隔离:只与本工作区 + builtin 的同名技能避让,
|
||||
// 不同工作区的同名技能不应互相影响命名)
|
||||
SkillEntity existing = skillService.findByName(name, workspaceId);
|
||||
if (existing != null) {
|
||||
name = name + "-" + (System.currentTimeMillis() % 10000);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user