mirror of
https://github.com/lukaszraczylo/filepuff-mcp.git
synced 2026-06-10 22:59:01 +00:00
Update, bugfixes on diff and edit handling
This commit is contained in:
@@ -120,6 +120,42 @@ func (e *StructuredError) WithRemediation(msg string) *StructuredError {
|
||||
return e
|
||||
}
|
||||
|
||||
// UserMessage returns a user-safe error message without internal details.
|
||||
// This should be used for API responses to avoid leaking implementation details.
|
||||
func (e *StructuredError) UserMessage() string {
|
||||
// Return only the message and remediation, no stack trace, no cause details
|
||||
if e.Remediation != "" {
|
||||
return fmt.Sprintf("%s. %s", e.Message, e.Remediation)
|
||||
}
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// SanitizeError returns a user-safe error message from any error.
|
||||
// For StructuredError, it returns UserMessage().
|
||||
// For other errors, it returns a generic message to avoid leaking internals.
|
||||
func SanitizeError(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Check if it's a StructuredError
|
||||
if se, ok := err.(*StructuredError); ok {
|
||||
return se.UserMessage()
|
||||
}
|
||||
|
||||
// For other errors, extract only the basic message
|
||||
// Avoid exposing full paths or implementation details
|
||||
msg := err.Error()
|
||||
|
||||
// Truncate very long messages that might contain stack traces
|
||||
const maxLen = 200
|
||||
if len(msg) > maxLen {
|
||||
msg = msg[:maxLen] + "..."
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
// New creates a new structured error with stack trace.
|
||||
func New(code ErrorCode, message string) *StructuredError {
|
||||
return &StructuredError{
|
||||
|
||||
+3
-13
@@ -1,6 +1,8 @@
|
||||
// Package protocol defines shared types used across the MCP file operations server.
|
||||
package protocol
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// Location represents a position in a file.
|
||||
type Location struct {
|
||||
File string `json:"file"`
|
||||
@@ -66,7 +68,7 @@ const (
|
||||
|
||||
// DetectLanguage detects the language from a filename.
|
||||
func DetectLanguage(filename string) Language {
|
||||
ext := getExtension(filename)
|
||||
ext := filepath.Ext(filename)
|
||||
switch ext {
|
||||
case ".go":
|
||||
return LangGo
|
||||
@@ -94,15 +96,3 @@ func DetectLanguage(filename string) Language {
|
||||
return LangUnknown
|
||||
}
|
||||
}
|
||||
|
||||
func getExtension(filename string) string {
|
||||
for i := len(filename) - 1; i >= 0; i-- {
|
||||
if filename[i] == '.' {
|
||||
return filename[i:]
|
||||
}
|
||||
if filename[i] == '/' || filename[i] == '\\' {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -48,26 +48,3 @@ func TestDetectLanguage(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtension(t *testing.T) {
|
||||
tests := []struct {
|
||||
filename string
|
||||
expected string
|
||||
}{
|
||||
{"file.go", ".go"},
|
||||
{"file.test.go", ".go"},
|
||||
{"path/to/file.ts", ".ts"},
|
||||
{"noextension", ""},
|
||||
{".hidden", ".hidden"},
|
||||
{"file.", "."},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.filename, func(t *testing.T) {
|
||||
result := getExtension(tt.filename)
|
||||
if result != tt.expected {
|
||||
t.Errorf("getExtension(%q) = %q, want %q", tt.filename, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user