============= Claude Skills 相关 API ============= ExportScriptsSkill 导出脚本为 Claude Skills 的 SKILL.md 格式
(c *gin.Context)
| 2939 | |
| 2940 | // ExportScriptsSkill 导出脚本为 Claude Skills 的 SKILL.md 格式 |
| 2941 | func (h *Handler) ExportScriptsSkill(c *gin.Context) { |
| 2942 | var req struct { |
| 2943 | ScriptIDs []string `json:"script_ids"` |
| 2944 | } |
| 2945 | |
| 2946 | if err := c.ShouldBindJSON(&req); err != nil { |
| 2947 | c.JSON(http.StatusBadRequest, gin.H{"error": "error.invalidRequest"}) |
| 2948 | return |
| 2949 | } |
| 2950 | |
| 2951 | // 获取脚本列表 |
| 2952 | var scripts []*models.Script |
| 2953 | var err error |
| 2954 | |
| 2955 | if len(req.ScriptIDs) == 0 { |
| 2956 | // 如果没有指定脚本ID,导出所有脚本 |
| 2957 | scripts, err = h.db.ListScripts() |
| 2958 | if err != nil { |
| 2959 | c.JSON(http.StatusInternalServerError, gin.H{"error": "error.listScriptsFailed"}) |
| 2960 | return |
| 2961 | } |
| 2962 | } else { |
| 2963 | // 导出指定的脚本 |
| 2964 | for _, id := range req.ScriptIDs { |
| 2965 | script, err := h.db.GetScript(id) |
| 2966 | if err != nil { |
| 2967 | continue // 跳过不存在的脚本 |
| 2968 | } |
| 2969 | scripts = append(scripts, script) |
| 2970 | } |
| 2971 | } |
| 2972 | |
| 2973 | if len(scripts) == 0 { |
| 2974 | c.JSON(http.StatusBadRequest, gin.H{"error": "error.noScriptsToExport"}) |
| 2975 | return |
| 2976 | } |
| 2977 | |
| 2978 | // 获取服务端地址 |
| 2979 | host := c.Request.Host |
| 2980 | |
| 2981 | // 判断是否导出所有脚本 |
| 2982 | isExportAll := len(req.ScriptIDs) == 0 |
| 2983 | |
| 2984 | // 收集脚本 ID |
| 2985 | scriptIDs := make([]string, len(scripts)) |
| 2986 | for i, script := range scripts { |
| 2987 | scriptIDs[i] = script.ID |
| 2988 | } |
| 2989 | |
| 2990 | // 生成 SKILL.md 内容 |
| 2991 | skillContent := generateSkillMD(scripts, host, isExportAll, scriptIDs) |
| 2992 | |
| 2993 | fileName := fmt.Sprintf("SKILL_%s.md", time.Now().Format("20060102150405")) |
| 2994 | |
| 2995 | // 返回内容 |
| 2996 | c.Header("Content-Type", "text/markdown; charset=utf-8") |
| 2997 | c.Header("Content-Disposition", "attachment; filename="+fileName) |
| 2998 | c.String(http.StatusOK, skillContent) |
nothing calls this directly
no test coverage detected