diff --git a/server/api/v1/system/sys_skills.go b/server/api/v1/system/sys_skills.go index b443ff63..056cddfc 100644 --- a/server/api/v1/system/sys_skills.go +++ b/server/api/v1/system/sys_skills.go @@ -125,6 +125,76 @@ func (s *SkillsApi) SaveResource(c *gin.Context) { response.OkWithMessage("保存成功", c) } +func (s *SkillsApi) CreateReference(c *gin.Context) { + var req request.SkillReferenceCreateRequest + _ = c.ShouldBindJSON(&req) + fileName, content, err := skillsService.CreateReference(c.Request.Context(), req) + if err != nil { + global.GVA_LOG.Error("创建参考失败", zap.Error(err)) + response.FailWithMessage("创建参考失败", c) + return + } + response.OkWithDetailed(gin.H{"fileName": fileName, "content": content}, "创建成功", c) +} + +func (s *SkillsApi) GetReference(c *gin.Context) { + var req request.SkillFileRequest + _ = c.ShouldBindJSON(&req) + content, err := skillsService.GetReference(c.Request.Context(), req) + if err != nil { + global.GVA_LOG.Error("读取参考失败", zap.Error(err)) + response.FailWithMessage("读取参考失败", c) + return + } + response.OkWithDetailed(gin.H{"content": content}, "获取成功", c) +} + +func (s *SkillsApi) SaveReference(c *gin.Context) { + var req request.SkillFileSaveRequest + _ = c.ShouldBindJSON(&req) + if err := skillsService.SaveReference(c.Request.Context(), req); err != nil { + global.GVA_LOG.Error("保存参考失败", zap.Error(err)) + response.FailWithMessage("保存参考失败", c) + return + } + response.OkWithMessage("保存成功", c) +} + +func (s *SkillsApi) CreateTemplate(c *gin.Context) { + var req request.SkillTemplateCreateRequest + _ = c.ShouldBindJSON(&req) + fileName, content, err := skillsService.CreateTemplate(c.Request.Context(), req) + if err != nil { + global.GVA_LOG.Error("创建模板失败", zap.Error(err)) + response.FailWithMessage("创建模板失败", c) + return + } + response.OkWithDetailed(gin.H{"fileName": fileName, "content": content}, "创建成功", c) +} + +func (s *SkillsApi) GetTemplate(c *gin.Context) { + var req request.SkillFileRequest + _ = c.ShouldBindJSON(&req) + content, err := skillsService.GetTemplate(c.Request.Context(), req) + if err != nil { + global.GVA_LOG.Error("读取模板失败", zap.Error(err)) + response.FailWithMessage("读取模板失败", c) + return + } + response.OkWithDetailed(gin.H{"content": content}, "获取成功", c) +} + +func (s *SkillsApi) SaveTemplate(c *gin.Context) { + var req request.SkillFileSaveRequest + _ = c.ShouldBindJSON(&req) + if err := skillsService.SaveTemplate(c.Request.Context(), req); err != nil { + global.GVA_LOG.Error("保存模板失败", zap.Error(err)) + response.FailWithMessage("保存模板失败", c) + return + } + response.OkWithMessage("保存成功", c) +} + func (s *SkillsApi) GetGlobalConstraint(c *gin.Context) { var req request.SkillToolRequest _ = c.ShouldBindJSON(&req) diff --git a/server/model/system/request/sys_skills.go b/server/model/system/request/sys_skills.go index b61d91e2..e9bb3066 100644 --- a/server/model/system/request/sys_skills.go +++ b/server/model/system/request/sys_skills.go @@ -32,6 +32,18 @@ type SkillResourceCreateRequest struct { FileName string `json:"fileName"` } +type SkillReferenceCreateRequest struct { + Tool string `json:"tool"` + Skill string `json:"skill"` + FileName string `json:"fileName"` +} + +type SkillTemplateCreateRequest struct { + Tool string `json:"tool"` + Skill string `json:"skill"` + FileName string `json:"fileName"` +} + type SkillFileRequest struct { Tool string `json:"tool"` Skill string `json:"skill"` diff --git a/server/model/system/sys_skills.go b/server/model/system/sys_skills.go index 76f6c341..e7013f62 100644 --- a/server/model/system/sys_skills.go +++ b/server/model/system/sys_skills.go @@ -9,12 +9,14 @@ type SkillMeta struct { } type SkillDetail struct { - Tool string `json:"tool"` - Skill string `json:"skill"` - Meta SkillMeta `json:"meta"` - Markdown string `json:"markdown"` - Scripts []string `json:"scripts"` - Resources []string `json:"resources"` + Tool string `json:"tool"` + Skill string `json:"skill"` + Meta SkillMeta `json:"meta"` + Markdown string `json:"markdown"` + Scripts []string `json:"scripts"` + Resources []string `json:"resources"` + References []string `json:"references"` + Templates []string `json:"templates"` } type SkillTool struct { diff --git a/server/router/system/sys_skills.go b/server/router/system/sys_skills.go index f631f62e..9529e66a 100644 --- a/server/router/system/sys_skills.go +++ b/server/router/system/sys_skills.go @@ -17,6 +17,12 @@ func (s *SkillsRouter) InitSkillsRouter(Router *gin.RouterGroup) { skillsRouter.POST("createResource", skillsApi.CreateResource) skillsRouter.POST("getResource", skillsApi.GetResource) skillsRouter.POST("saveResource", skillsApi.SaveResource) + skillsRouter.POST("createReference", skillsApi.CreateReference) + skillsRouter.POST("getReference", skillsApi.GetReference) + skillsRouter.POST("saveReference", skillsApi.SaveReference) + skillsRouter.POST("createTemplate", skillsApi.CreateTemplate) + skillsRouter.POST("getTemplate", skillsApi.GetTemplate) + skillsRouter.POST("saveTemplate", skillsApi.SaveTemplate) skillsRouter.POST("getGlobalConstraint", skillsApi.GetGlobalConstraint) skillsRouter.POST("saveGlobalConstraint", skillsApi.SaveGlobalConstraint) } diff --git a/server/service/system/sys_skills.go b/server/service/system/sys_skills.go index 51b79c65..090fc927 100644 --- a/server/service/system/sys_skills.go +++ b/server/service/system/sys_skills.go @@ -43,6 +43,10 @@ const defaultSkillMarkdown = "## 技能用途\n请在这里描述技能的目标 const defaultResourceMarkdown = "# 资源说明\n请在这里补充资源内容。\n" +const defaultReferenceMarkdown = "# 参考资料\n请在这里补充参考资料内容。\n" + +const defaultTemplateMarkdown = "# 模板\n请在这里补充模板内容。\n" + const defaultGlobalConstraintMarkdown = "# 全局约束\n请在这里补充该工具的统一约束与使用规范。\n" type SkillsService struct{} @@ -113,6 +117,8 @@ func (s *SkillsService) Detail(_ context.Context, tool, skill string) (system.Sk detail.Scripts = listFiles(filepath.Join(skillDir, "scripts")) detail.Resources = listFiles(filepath.Join(skillDir, "resources")) + detail.References = listFiles(filepath.Join(skillDir, "references")) + detail.Templates = listFiles(filepath.Join(skillDir, "templates")) return detail, nil } @@ -190,29 +196,7 @@ func (s *SkillsService) SaveScript(_ context.Context, req request.SkillFileSaveR } func (s *SkillsService) CreateResource(_ context.Context, req request.SkillResourceCreateRequest) (string, string, error) { - if !isSafeName(req.Skill) { - return "", "", errors.New("技能名称不合法") - } - fileName, err := buildResourceFileName(req.FileName) - if err != nil { - return "", "", err - } - skillDir, err := s.ensureSkillDir(req.Tool, req.Skill) - if err != nil { - return "", "", err - } - filePath := filepath.Join(skillDir, "resources", fileName) - if _, err := os.Stat(filePath); err == nil { - return "", "", errors.New("资源已存在") - } - if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { - return "", "", err - } - content := defaultResourceMarkdown - if err := os.WriteFile(filePath, []byte(content), 0644); err != nil { - return "", "", err - } - return fileName, content, nil + return s.createMarkdownFile(req.Tool, req.Skill, "resources", req.FileName, defaultResourceMarkdown, "资源") } func (s *SkillsService) GetResource(_ context.Context, req request.SkillFileRequest) (string, error) { @@ -223,6 +207,30 @@ func (s *SkillsService) SaveResource(_ context.Context, req request.SkillFileSav return s.writeSkillFile(req.Tool, req.Skill, "resources", req.FileName, req.Content) } +func (s *SkillsService) CreateReference(_ context.Context, req request.SkillReferenceCreateRequest) (string, string, error) { + return s.createMarkdownFile(req.Tool, req.Skill, "references", req.FileName, defaultReferenceMarkdown, "参考") +} + +func (s *SkillsService) GetReference(_ context.Context, req request.SkillFileRequest) (string, error) { + return s.readSkillFile(req.Tool, req.Skill, "references", req.FileName) +} + +func (s *SkillsService) SaveReference(_ context.Context, req request.SkillFileSaveRequest) error { + return s.writeSkillFile(req.Tool, req.Skill, "references", req.FileName, req.Content) +} + +func (s *SkillsService) CreateTemplate(_ context.Context, req request.SkillTemplateCreateRequest) (string, string, error) { + return s.createMarkdownFile(req.Tool, req.Skill, "templates", req.FileName, defaultTemplateMarkdown, "模板") +} + +func (s *SkillsService) GetTemplate(_ context.Context, req request.SkillFileRequest) (string, error) { + return s.readSkillFile(req.Tool, req.Skill, "templates", req.FileName) +} + +func (s *SkillsService) SaveTemplate(_ context.Context, req request.SkillFileSaveRequest) error { + return s.writeSkillFile(req.Tool, req.Skill, "templates", req.FileName, req.Content) +} + func (s *SkillsService) GetGlobalConstraint(_ context.Context, tool string) (string, bool, error) { skillsDir, err := s.toolSkillsDir(tool) if err != nil { @@ -309,6 +317,35 @@ func (s *SkillsService) ensureSkillDir(tool, skill string) (string, error) { return skillDir, nil } +func (s *SkillsService) createMarkdownFile(tool, skill, subDir, fileName, defaultContent, label string) (string, string, error) { + if !isSafeName(skill) { + return "", "", errors.New("技能名称不合法") + } + cleanName, err := buildResourceFileName(fileName) + if err != nil { + return "", "", err + } + skillDir, err := s.ensureSkillDir(tool, skill) + if err != nil { + return "", "", err + } + filePath := filepath.Join(skillDir, subDir, cleanName) + if _, err := os.Stat(filePath); err == nil { + if label == "" { + label = "文件" + } + return "", "", fmt.Errorf("%s已存在", label) + } + if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { + return "", "", err + } + content := defaultContent + if err := os.WriteFile(filePath, []byte(content), 0644); err != nil { + return "", "", err + } + return cleanName, content, nil +} + func (s *SkillsService) readSkillFile(tool, skill, subDir, fileName string) (string, error) { if !isSafeName(skill) { return "", errors.New("技能名称不合法") diff --git a/server/source/system/api.go b/server/source/system/api.go index 3632840e..9ab2e427 100644 --- a/server/source/system/api.go +++ b/server/source/system/api.go @@ -124,6 +124,12 @@ func (i *initApi) InitializeData(ctx context.Context) (context.Context, error) { {ApiGroup: "skills", Method: "POST", Path: "/skills/createResource", Description: "创建技能资源"}, {ApiGroup: "skills", Method: "POST", Path: "/skills/getResource", Description: "读取技能资源"}, {ApiGroup: "skills", Method: "POST", Path: "/skills/saveResource", Description: "保存技能资源"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/createReference", Description: "创建技能参考"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/getReference", Description: "读取技能参考"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/saveReference", Description: "保存技能参考"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/createTemplate", Description: "创建技能模板"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/getTemplate", Description: "读取技能模板"}, + {ApiGroup: "skills", Method: "POST", Path: "/skills/saveTemplate", Description: "保存技能模板"}, {ApiGroup: "skills", Method: "POST", Path: "/skills/getGlobalConstraint", Description: "读取全局约束"}, {ApiGroup: "skills", Method: "POST", Path: "/skills/saveGlobalConstraint", Description: "保存全局约束"}, diff --git a/server/source/system/casbin.go b/server/source/system/casbin.go index 0cdf22ec..e265f90a 100644 --- a/server/source/system/casbin.go +++ b/server/source/system/casbin.go @@ -126,6 +126,12 @@ func (i *initCasbin) InitializeData(ctx context.Context) (context.Context, error {Ptype: "p", V0: "888", V1: "/skills/createResource", V2: "POST"}, {Ptype: "p", V0: "888", V1: "/skills/getResource", V2: "POST"}, {Ptype: "p", V0: "888", V1: "/skills/saveResource", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/createReference", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/getReference", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/saveReference", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/createTemplate", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/getTemplate", V2: "POST"}, + {Ptype: "p", V0: "888", V1: "/skills/saveTemplate", V2: "POST"}, {Ptype: "p", V0: "888", V1: "/skills/getGlobalConstraint", V2: "POST"}, {Ptype: "p", V0: "888", V1: "/skills/saveGlobalConstraint", V2: "POST"}, diff --git a/web/src/api/skills.js b/web/src/api/skills.js index 0a9dbb21..3425a7ce 100644 --- a/web/src/api/skills.js +++ b/web/src/api/skills.js @@ -79,6 +79,54 @@ export const saveSkillResource = (data) => { }) } +export const createSkillReference = (data) => { + return service({ + url: '/skills/createReference', + method: 'post', + data + }) +} + +export const getSkillReference = (data) => { + return service({ + url: '/skills/getReference', + method: 'post', + data + }) +} + +export const saveSkillReference = (data) => { + return service({ + url: '/skills/saveReference', + method: 'post', + data + }) +} + +export const createSkillTemplate = (data) => { + return service({ + url: '/skills/createTemplate', + method: 'post', + data + }) +} + +export const getSkillTemplate = (data) => { + return service({ + url: '/skills/getTemplate', + method: 'post', + data + }) +} + +export const saveSkillTemplate = (data) => { + return service({ + url: '/skills/saveTemplate', + method: 'post', + data + }) +} + export const getGlobalConstraint = (data) => { return service({ url: '/skills/getGlobalConstraint',