Commit 8e5cd0f

mo khan <mo@mokhan.ca>
2025-06-23 00:20:33
feat: ask Claude :shrug:
1 parent 14c66d8
Changed files (1)
cmd
cmd/del/main.go
@@ -67,13 +67,13 @@ func NewDel(model string) *Del {
 				Content: `You are Del, an AI coding assistant. When users need file operations or code analysis, use your available tools.
 
 Available tools:
-- read_file: Read file contents (requires: path)
-- list_dir: List directory contents (optional: path, defaults to current dir)
-- run_command: Execute shell commands (requires: command)
-- git_status: Check git repository status (no args needed)
-- write_file: Write content to files (requires: path, content)
-- analyze_code: Analyze code structure (optional: path, content, language - auto-detects files if none provided)
-- search_code: Search for patterns in code (requires: pattern, optional: path)
+- read_file: Read file contents
+- list_dir: List directory contents  
+- run_command: Execute shell commands
+- git_status: Check git repository status
+- write_file: Write content to files
+- analyze_code: Analyze code structure (auto-detects files if no path provided)
+- search_code: Search for patterns in code
 
 Use tools by generating calls in this format:
 function<|tool▁sep|>tool_name
@@ -85,7 +85,15 @@ EXAMPLES:
 - When user says "read main.go": use read_file with {"path": "main.go"}
 - When user says "check git status": use git_status with {}
 
-IMPORTANT: Stop immediately after making tool calls. Don't generate fake results or outputs.`,
+FORMATTING: Always format your responses using markdown. Use:
+- ## Headers for main sections
+- **bold** for important terms
+- backticks for inline code, file names, and commands
+- - bullet points for lists
+- 1. numbered lists for steps
+- code blocks for multi-line code
+
+IMPORTANT: Use tools first, then provide a natural markdown response based on the results.`,
 			},
 		},
 	}
@@ -107,6 +115,102 @@ func isCodeFile(name string) bool {
 		   strings.HasSuffix(name, ".rb") || strings.HasSuffix(name, ".php")
 }
 
+// ANSI color codes for terminal formatting
+const (
+	ColorReset  = "\033[0m"
+	ColorBold   = "\033[1m"
+	ColorDim    = "\033[2m"
+	ColorItalic = "\033[3m"
+	ColorRed    = "\033[31m"
+	ColorGreen  = "\033[32m"
+	ColorYellow = "\033[33m"
+	ColorBlue   = "\033[34m"
+	ColorPurple = "\033[35m"
+	ColorCyan   = "\033[36m"
+	ColorWhite  = "\033[37m"
+	ColorGray   = "\033[90m"
+)
+
+// renderMarkdown converts markdown text to terminal-formatted output
+func renderMarkdown(text string) string {
+	lines := strings.Split(text, "\n")
+	var result []string
+	inCodeBlock := false
+	
+	for _, line := range lines {
+		// Code blocks
+		if strings.HasPrefix(line, "```") {
+			inCodeBlock = !inCodeBlock
+			if inCodeBlock {
+				result = append(result, ColorGray+"┌─────────────────────────────────────────────────────────┐"+ColorReset)
+			} else {
+				result = append(result, ColorGray+"└─────────────────────────────────────────────────────────┘"+ColorReset)
+			}
+			continue
+		}
+		
+		if inCodeBlock {
+			result = append(result, ColorGray+"│ "+ColorCyan+line+ColorReset+ColorGray+" │"+ColorReset)
+			continue
+		}
+		
+		// Headers
+		if strings.HasPrefix(line, "### ") {
+			header := strings.TrimPrefix(line, "### ")
+			result = append(result, "")
+			result = append(result, ColorBold+ColorBlue+"▸ "+header+ColorReset)
+			continue
+		}
+		if strings.HasPrefix(line, "## ") {
+			header := strings.TrimPrefix(line, "## ")
+			result = append(result, "")
+			result = append(result, ColorBold+ColorGreen+"◆ "+header+ColorReset)
+			continue
+		}
+		if strings.HasPrefix(line, "# ") {
+			header := strings.TrimPrefix(line, "# ")
+			result = append(result, "")
+			result = append(result, ColorBold+ColorYellow+"● "+header+ColorReset)
+			continue
+		}
+		
+		// Lists
+		if strings.HasPrefix(line, "- ") || regexp.MustCompile(`^\d+\. `).MatchString(line) {
+			// Handle numbered lists
+			if regexp.MustCompile(`^\d+\. `).MatchString(line) {
+				parts := regexp.MustCompile(`^(\d+)\. (.*)$`).FindStringSubmatch(line)
+				if len(parts) == 3 {
+					line = ColorBold+ColorBlue+parts[1]+"."+ColorReset+" "+parts[2]
+				}
+			} else {
+				// Handle bullet lists
+				content := strings.TrimPrefix(line, "- ")
+				line = ColorBold+ColorGreen+"•"+ColorReset+" "+content
+			}
+			result = append(result, "  "+line)
+			continue
+		}
+		
+		// Inline code
+		line = regexp.MustCompile("`([^`]+)`").ReplaceAllString(line, ColorCyan+"$1"+ColorReset)
+		
+		// Bold text
+		line = regexp.MustCompile(`\*\*([^*]+)\*\*`).ReplaceAllString(line, ColorBold+"$1"+ColorReset)
+		
+		// Italic text  
+		line = regexp.MustCompile(`\*([^*]+)\*`).ReplaceAllString(line, ColorItalic+"$1"+ColorReset)
+		
+		// Empty lines for spacing
+		if strings.TrimSpace(line) == "" {
+			result = append(result, "")
+		} else {
+			result = append(result, line)
+		}
+	}
+	
+	return strings.Join(result, "\n")
+}
+
 func (d *Del) registerTools() {
 	d.tools["read_file"] = d.readFile
 	d.tools["list_dir"] = d.listDir
@@ -714,25 +818,11 @@ func (d *Del) formatArgs(args map[string]interface{}) string {
 }
 
 func (d *Del) streamResponseChunks(ctx context.Context, text string) {
-	// Real streaming simulation - send in meaningful chunks
-	words := strings.Fields(text)
-	for i, word := range words {
-		d.emit(StreamMessage{
-			Type:    MessageTypeAssistant,
-			Content: word,
-		})
-		
-		// Natural pause between words
-		if i < len(words)-1 {
-			d.emit(StreamMessage{
-				Type:    MessageTypeAssistant,
-				Content: " ",
-			})
-		}
-		
-		// Small delay for natural typing feel
-		time.Sleep(20 * time.Millisecond)
-	}
+	// Instead of word-by-word streaming, send the full response for better markdown rendering
+	d.emit(StreamMessage{
+		Type:    MessageTypeAssistant,
+		Content: text,
+	})
 }
 
 func (d *Del) processMessage(ctx context.Context, userInput string) {
@@ -811,11 +901,24 @@ func (d *Del) renderUI() {
 			currentLine = ""
 			
 		case MessageTypeAssistant:
-			if currentLine == "" {
-				fmt.Print("🤖 Del: ")
+			if currentLine != "" {
+				fmt.Println()
 			}
-			fmt.Print(msg.Content)
-			currentLine += msg.Content
+			fmt.Print("🤖 Del: ")
+			
+			// Render markdown content
+			rendered := renderMarkdown(msg.Content)
+			
+			// Indent the content to align with the prefix
+			lines := strings.Split(rendered, "\n")
+			for i, line := range lines {
+				if i == 0 {
+					fmt.Println(line)
+				} else {
+					fmt.Printf("        %s\n", line) // 8 spaces to align with "🤖 Del: "
+				}
+			}
+			currentLine = ""
 			
 		case MessageTypeTool:
 			if currentLine != "" {