diff options
Diffstat (limited to 'internal/slashcommands/converter.go')
| -rw-r--r-- | internal/slashcommands/converter.go | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/internal/slashcommands/converter.go b/internal/slashcommands/converter.go new file mode 100644 index 0000000..87c77c8 --- /dev/null +++ b/internal/slashcommands/converter.go @@ -0,0 +1,113 @@ +// Summary: Converts MCP prompts to generic slash command Markdown format. +package slashcommands + +import ( + "fmt" + "regexp" + "strings" + + "codeberg.org/snonux/hexai/internal/promptstore" +) + +// ConvertPromptToMarkdown converts an MCP prompt to slash command Markdown. +// Returns a formatted Markdown string suitable for writing to a .md file. +func ConvertPromptToMarkdown(prompt *promptstore.Prompt) string { + var sb strings.Builder + + // Title + sb.WriteString("# ") + sb.WriteString(prompt.Title) + sb.WriteString("\n\n") + + // Description + if prompt.Description != "" { + sb.WriteString(prompt.Description) + sb.WriteString("\n\n") + } + + // Arguments section + if len(prompt.Arguments) > 0 { + sb.WriteString(formatArguments(prompt.Arguments)) + sb.WriteString("\n") + } + + // Template section (first user message) + if len(prompt.Messages) > 0 { + sb.WriteString("## Template\n\n") + sb.WriteString(formatMessages(prompt.Messages)) + sb.WriteString("\n\n") + } + + // Tags section + if len(prompt.Tags) > 0 { + sb.WriteString("## Tags\n\n") + sb.WriteString(strings.Join(prompt.Tags, ", ")) + sb.WriteString("\n\n") + } + + // Footer + sb.WriteString("---\n") + sb.WriteString("*Generated from MCP prompt: ") + sb.WriteString(prompt.Name) + sb.WriteString("*\n") + + return sb.String() +} + +// formatArguments creates the Usage section with argument documentation. +// Returns formatted Markdown listing all arguments with their properties. +func formatArguments(args []promptstore.PromptArgument) string { + var sb strings.Builder + + sb.WriteString("## Usage\n\n") + sb.WriteString("This prompt template accepts the following arguments:\n\n") + + for _, arg := range args { + // Format: - **arg_name** (required/optional): Description + sb.WriteString("- **") + sb.WriteString(arg.Name) + sb.WriteString("** (") + if arg.Required { + sb.WriteString("required") + } else { + sb.WriteString("optional") + } + sb.WriteString("): ") + sb.WriteString(arg.Description) + sb.WriteString("\n") + } + + return sb.String() +} + +// formatMessages extracts the first user message for the Template section. +// Shows users what the prompt template looks like with {{placeholders}}. +func formatMessages(messages []promptstore.PromptMessage) string { + // Find first user message + for _, msg := range messages { + if msg.Role == "user" && msg.Content.Text != "" { + return msg.Content.Text + } + } + return "(No template content)" +} + +// sanitizeFilename ensures prompt name is valid for filename. +// Replaces non-alphanumeric characters with hyphens. +func sanitizeFilename(name string) string { + // Replace any character that's not alphanumeric or underscore with hyphen + re := regexp.MustCompile(`[^a-zA-Z0-9_]+`) + sanitized := re.ReplaceAllString(name, "-") + + // Remove leading/trailing hyphens + sanitized = strings.Trim(sanitized, "-") + + // Convert to lowercase for consistency + return strings.ToLower(sanitized) +} + +// MakeFilename creates a slash command filename with hexai- prefix. +// Returns: hexai-{sanitized_name}.md +func MakeFilename(promptName string) string { + return fmt.Sprintf("hexai-%s.md", sanitizeFilename(promptName)) +} |
