* Implement tests for error functions like errRequiredField, errInvalidField, and errEntityNotFound. * Ensure proper metadata is returned for various error scenarios. * Validate error handling in CRM, Files, and other tools. * Introduce tests for parsing stored file IDs and UUIDs. * Enhance coverage for helper functions related to project resolution and session management.
146 lines
3.0 KiB
Go
146 lines
3.0 KiB
Go
package tools
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.warky.dev/wdevs/amcs/internal/config"
|
|
"git.warky.dev/wdevs/amcs/internal/mcperrors"
|
|
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
|
|
)
|
|
|
|
func normalizeLimit(limit int, cfg config.SearchConfig) int {
|
|
if limit <= 0 {
|
|
return cfg.DefaultLimit
|
|
}
|
|
if limit > cfg.MaxLimit {
|
|
return cfg.MaxLimit
|
|
}
|
|
return limit
|
|
}
|
|
|
|
func normalizeThreshold(value float64, fallback float64) float64 {
|
|
if value <= 0 {
|
|
return fallback
|
|
}
|
|
if value > 1 {
|
|
return 1
|
|
}
|
|
return value
|
|
}
|
|
|
|
const (
|
|
codeSessionRequired = mcperrors.CodeSessionRequired
|
|
codeProjectRequired = mcperrors.CodeProjectRequired
|
|
codeProjectNotFound = mcperrors.CodeProjectNotFound
|
|
codeInvalidID = mcperrors.CodeInvalidID
|
|
codeEntityNotFound = mcperrors.CodeEntityNotFound
|
|
)
|
|
|
|
type mcpErrorData = mcperrors.Data
|
|
|
|
func newMCPError(code int64, message string, data mcpErrorData) error {
|
|
rpcErr := &jsonrpc.Error{
|
|
Code: code,
|
|
Message: message,
|
|
}
|
|
|
|
payload, err := json.Marshal(data)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal mcp error data: %w", err)
|
|
}
|
|
rpcErr.Data = payload
|
|
|
|
return rpcErr
|
|
}
|
|
|
|
func errInvalidInput(message string) error {
|
|
return newMCPError(
|
|
jsonrpc.CodeInvalidParams,
|
|
"invalid input: "+message,
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeInvalidInput,
|
|
},
|
|
)
|
|
}
|
|
|
|
func errRequiredField(field string) error {
|
|
return newMCPError(
|
|
jsonrpc.CodeInvalidParams,
|
|
field+" is required",
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeInvalidInput,
|
|
Field: field,
|
|
Detail: "required",
|
|
Hint: "provide " + field,
|
|
},
|
|
)
|
|
}
|
|
|
|
func errInvalidField(field string, message string, hint string) error {
|
|
return newMCPError(
|
|
jsonrpc.CodeInvalidParams,
|
|
message,
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeInvalidInput,
|
|
Field: field,
|
|
Detail: "invalid",
|
|
Hint: hint,
|
|
},
|
|
)
|
|
}
|
|
|
|
func errOneOfRequired(fields ...string) error {
|
|
return newMCPError(
|
|
jsonrpc.CodeInvalidParams,
|
|
joinFields(fields)+" is required",
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeInvalidInput,
|
|
Fields: fields,
|
|
Detail: "one_of_required",
|
|
Hint: "provide one of: " + strings.Join(fields, ", "),
|
|
},
|
|
)
|
|
}
|
|
|
|
func errMutuallyExclusiveFields(fields ...string) error {
|
|
return newMCPError(
|
|
jsonrpc.CodeInvalidParams,
|
|
"provide "+joinFields(fields)+", not both",
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeInvalidInput,
|
|
Fields: fields,
|
|
Detail: "mutually_exclusive",
|
|
Hint: "provide only one of: " + strings.Join(fields, ", "),
|
|
},
|
|
)
|
|
}
|
|
|
|
func errEntityNotFound(entity string, field string, value string) error {
|
|
return newMCPError(
|
|
codeEntityNotFound,
|
|
entity+" not found",
|
|
mcpErrorData{
|
|
Type: mcperrors.TypeEntityNotFound,
|
|
Entity: entity,
|
|
Field: field,
|
|
Value: value,
|
|
Detail: "not_found",
|
|
},
|
|
)
|
|
}
|
|
|
|
func joinFields(fields []string) string {
|
|
switch len(fields) {
|
|
case 0:
|
|
return "field"
|
|
case 1:
|
|
return fields[0]
|
|
case 2:
|
|
return fields[0] + " or " + fields[1]
|
|
default:
|
|
return strings.Join(fields[:len(fields)-1], ", ") + ", or " + fields[len(fields)-1]
|
|
}
|
|
}
|