refactor: move DoAction to MCP tools call

This commit is contained in:
lilong.129
2025-05-25 08:10:57 +08:00
parent 4ff2692f02
commit 7986c4899f
8 changed files with 2220 additions and 359 deletions
+132
View File
@@ -92,10 +92,125 @@ type PressButtonRequest struct {
Button types.DeviceButton `json:"button" binding:"required" desc:"The button to press. Supported buttons: BACK (android only), HOME, VOLUME_UP, VOLUME_DOWN, ENTER."`
}
// Additional requests for missing actions
type WebLoginNoneUIRequest struct {
TargetDeviceRequest
PackageName string `json:"packageName" binding:"required" desc:"Package name for the app to login"`
PhoneNumber string `json:"phoneNumber" binding:"required" desc:"Phone number for login"`
Captcha string `json:"captcha" binding:"required" desc:"Captcha code"`
Password string `json:"password" binding:"required" desc:"Password for login"`
}
type SwipeToTapAppRequest struct {
TargetDeviceRequest
AppName string `json:"appName" binding:"required" desc:"App name to find and tap"`
}
type SwipeToTapTextRequest struct {
TargetDeviceRequest
Text string `json:"text" binding:"required" desc:"Text to find and tap"`
}
type SwipeToTapTextsRequest struct {
TargetDeviceRequest
Texts []string `json:"texts" binding:"required" desc:"List of texts to find and tap"`
}
type SecondaryClickRequest struct {
TargetDeviceRequest
X float64 `json:"x" binding:"required" desc:"X coordinate (0.0~1.0 for percent, or absolute pixel value)"`
Y float64 `json:"y" binding:"required" desc:"Y coordinate (0.0~1.0 for percent, or absolute pixel value)"`
}
type SelectorRequest struct {
TargetDeviceRequest
Selector string `json:"selector" binding:"required" desc:"CSS or XPath selector"`
}
type WebCloseTabRequest struct {
TargetDeviceRequest
TabIndex int `json:"tabIndex" binding:"required" desc:"Index of the tab to close"`
}
type SetImeRequest struct {
TargetDeviceRequest
Ime string `json:"ime" binding:"required" desc:"IME package name to set"`
}
type GetSourceRequest struct {
TargetDeviceRequest
PackageName string `json:"packageName" binding:"required" desc:"Package name to get source from"`
}
type TapAbsXYRequest struct {
TargetDeviceRequest
X float64 `json:"x" binding:"required" desc:"Absolute X coordinate in pixels"`
Y float64 `json:"y" binding:"required" desc:"Absolute Y coordinate in pixels"`
Duration float64 `json:"duration" desc:"Tap duration in seconds (optional)"`
}
type TapByOCRRequest struct {
TargetDeviceRequest
Text string `json:"text" binding:"required" desc:"OCR text to find and tap"`
}
type TapByCVRequest struct {
TargetDeviceRequest
ImagePath string `json:"imagePath" desc:"Path to reference image for CV recognition"`
}
type DoubleTapXYRequest struct {
TargetDeviceRequest
X float64 `json:"x" binding:"required" desc:"X coordinate (0.0~1.0 for percent, or absolute pixel value)"`
Y float64 `json:"y" binding:"required" desc:"Y coordinate (0.0~1.0 for percent, or absolute pixel value)"`
}
type SwipeAdvancedRequest struct {
TargetDeviceRequest
FromX float64 `json:"fromX" binding:"required" desc:"Starting X coordinate"`
FromY float64 `json:"fromY" binding:"required" desc:"Starting Y coordinate"`
ToX float64 `json:"toX" binding:"required" desc:"Ending X coordinate"`
ToY float64 `json:"toY" binding:"required" desc:"Ending Y coordinate"`
Duration float64 `json:"duration" desc:"Swipe duration in seconds (optional)"`
PressDuration float64 `json:"pressDuration" desc:"Press duration in seconds (optional)"`
}
type SleepMSRequest struct {
TargetDeviceRequest
Milliseconds int64 `json:"milliseconds" binding:"required" desc:"Sleep duration in milliseconds"`
}
type SleepRandomRequest struct {
TargetDeviceRequest
Params []float64 `json:"params" binding:"required" desc:"Random sleep parameters [min, max] or [min1, max1, weight1, ...]"`
}
type CallFunctionRequest struct {
TargetDeviceRequest
Description string `json:"description" binding:"required" desc:"Function description"`
}
type AIActionRequest struct {
TargetDeviceRequest
Prompt string `json:"prompt" binding:"required" desc:"AI action prompt"`
}
// NewMCPOptions generates mcp.NewTool parameters from a struct type.
// It automatically generates mcp.NewTool parameters based on the struct fields and their desc tags.
func NewMCPOptions(t interface{}) (options []mcp.ToolOption) {
tType := reflect.TypeOf(t)
// Handle pointer type by getting the element type
if tType.Kind() == reflect.Ptr {
tType = tType.Elem()
}
// Ensure we have a struct type
if tType.Kind() != reflect.Struct {
log.Warn().Str("type", tType.String()).Msg("NewMCPOptions expects a struct or pointer to struct")
return options
}
for i := 0; i < tType.NumField(); i++ {
field := tType.Field(i)
jsonTag := field.Tag.Get("json")
@@ -125,6 +240,23 @@ func NewMCPOptions(t interface{}) (options []mcp.ToolOption) {
} else {
options = append(options, mcp.WithBoolean(name, mcp.Description(desc)))
}
case reflect.Slice:
// Handle slice types, especially []string and []float64
if field.Type.Elem().Kind() == reflect.String {
// Array of strings
if required {
options = append(options, mcp.WithArray(name, mcp.Required(), mcp.Description(desc)))
} else {
options = append(options, mcp.WithArray(name, mcp.Description(desc)))
}
} else if field.Type.Elem().Kind() == reflect.Float64 {
// Array of numbers
if required {
options = append(options, mcp.WithArray(name, mcp.Required(), mcp.Description(desc)))
} else {
options = append(options, mcp.WithArray(name, mcp.Description(desc)))
}
}
default:
log.Warn().Str("field_type", field.Type.String()).Msg("Unsupported field type")
}