From 429479d3a315b43bb604b48cffeedb577715e646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Mon, 14 Jul 2025 15:25:15 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96driver=E5=B1=82?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=A0=81=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/driver_session.go | 21 +++++++++++++++++---- uixt/ios_device.go | 2 +- uixt/ios_driver_wda.go | 12 ++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/uixt/driver_session.go b/uixt/driver_session.go index 4c654398..89dd47d6 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -18,6 +18,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/uixt/option" ) @@ -153,21 +154,33 @@ func (s *DriverSession) buildURL(urlStr string) (string, error) { } func (s *DriverSession) GET(urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { - return s.RequestWithRetry(http.MethodGet, urlStr, nil, opts...) + rawResp, err = s.RequestWithRetry(http.MethodGet, urlStr, nil, opts...) + if err != nil { + return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + } + return rawResp, nil } func (s *DriverSession) POST(data interface{}, urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { var bsJSON []byte = nil if data != nil { if bsJSON, err = json.Marshal(data); err != nil { - return nil, err + return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) } } - return s.RequestWithRetry(http.MethodPost, urlStr, bsJSON, opts...) + rawResp, err = s.RequestWithRetry(http.MethodPost, urlStr, bsJSON, opts...) + if err != nil { + return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + } + return rawResp, nil } func (s *DriverSession) DELETE(urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { - return s.RequestWithRetry(http.MethodDelete, urlStr, nil, opts...) + rawResp, err = s.RequestWithRetry(http.MethodDelete, urlStr, nil, opts...) + if err != nil { + return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + } + return rawResp, nil } func (s *DriverSession) RequestWithRetry(method string, urlStr string, rawBody []byte, opts ...option.ActionOption) ( diff --git a/uixt/ios_device.go b/uixt/ios_device.go index 0c220006..ba16502f 100644 --- a/uixt/ios_device.go +++ b/uixt/ios_device.go @@ -231,7 +231,7 @@ func (dev *IOSDevice) NewDriver() (driver IDriver, err error) { if dev.Options.ResetHomeOnStartup { log.Info().Msg("go back to home screen") if err = wdaDriver.Home(); err != nil { - return nil, errors.Wrap(code.MobileUIDriverError, + return nil, errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("go back to home screen failed: %v", err)) } } diff --git a/uixt/ios_driver_wda.go b/uixt/ios_driver_wda.go index c2735e55..6cdb5ca2 100644 --- a/uixt/ios_driver_wda.go +++ b/uixt/ios_driver_wda.go @@ -196,7 +196,7 @@ func (wd *WDADriver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) { // [[FBRoute GET:@"/wda/device/info"].withoutSession var rawResp DriverRawResponse if rawResp, err = wd.Session.GET("/wda/device/info"); err != nil { - return types.DeviceInfo{}, err + return types.DeviceInfo{}, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) } reply := new(struct{ Value struct{ types.DeviceInfo } }) if err = json.Unmarshal(rawResp, reply); err != nil { @@ -268,7 +268,7 @@ func (wd *WDADriver) Scale() (float64, error) { } screen, err := wd.Screen() if err != nil { - return 0, errors.Wrap(code.MobileUIDriverError, + return 0, errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("get screen info failed: %v", err)) } return screen.Scale, nil @@ -298,12 +298,12 @@ func (wd *WDADriver) ScreenShot(opts ...option.ActionOption) (raw *bytes.Buffer, // [[FBRoute GET:@"/screenshot"].withoutSession respondWithTarget:self action:@selector(handleGetScreenshot:)] rawResp, err := wd.Session.GET("/screenshot") if err != nil { - return nil, errors.Wrap(code.DeviceScreenShotError, + return nil, errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("WDA screenshot failed %v", err)) } raw, err = rawResp.ValueDecodeAsBase64() if err != nil { - return nil, errors.Wrap(code.DeviceScreenShotError, + return nil, errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("decode WDA screenshot data failed: %v", err)) } return raw, nil @@ -454,7 +454,7 @@ func (wd *WDADriver) AppLaunch(bundleId string) (err error) { } _, err = wd.Session.POST(data, "/wings/apps/launch") if err != nil { - return errors.Wrap(code.MobileUILaunchAppError, + return errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("wda launch failed: %v", err)) } return nil @@ -466,7 +466,7 @@ func (wd *WDADriver) AppLaunchUnattached(bundleId string) (err error) { data := map[string]interface{}{"bundleId": bundleId} _, err = wd.Session.POST(data, "/wda/apps/launchUnattached") if err != nil { - return errors.Wrap(code.MobileUILaunchAppError, + return errors.Wrap(code.DeviceHTTPDriverError, fmt.Sprintf("wda launchUnattached failed: %v", err)) } return nil From b598c162a9780a21240ac5641c0b2f494a3f4b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Tue, 15 Jul 2025 20:18:40 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Elogid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uixt/driver_session.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uixt/driver_session.go b/uixt/driver_session.go index 89dd47d6..ab837c9a 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -233,6 +234,7 @@ func (s *DriverSession) RequestWithRetry(method string, urlStr string, rawBody [ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, opts ...option.ActionOption) ( rawResp DriverRawResponse, err error, ) { + logid := uuid.New().String() timeout := s.timeout options := option.NewActionOptions(opts...) if options.Timeout > 0 { @@ -264,7 +266,7 @@ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, op logger = log.Debug().Bool("success", true) } - logger = logger.Str("request_method", method).Str("request_url", rawURL). + logger = logger.Str("logid", logid).Str("request_method", method).Str("request_url", rawURL). Str("request_body", string(rawBody)) if !driverResult.RequestTime.IsZero() { logger = logger.Int64("request_time", driverResult.RequestTime.UnixMilli()) @@ -287,6 +289,8 @@ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, op } req.Header.Set("Content-Type", "application/json;charset=UTF-8") req.Header.Set("Accept", "application/json") + req.Header.Set("X-HTTP-Request-ID", logid) + req.Header.Set("logid", logid) driverResult.RequestTime = time.Now() var resp *http.Response From 6dfeb02677972d7ca0f4030f9ba6ccbf1ecc01ce Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Wed, 16 Jul 2025 00:26:34 +0800 Subject: [PATCH 3/4] fix: preserve the original error code for mcp tools --- go.mod | 2 +- internal/version/VERSION | 2 +- uixt/sdk.go | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index ca680fc9..3abfe4f7 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/gin-gonic/gin v1.10.0 github.com/go-openapi/spec v0.20.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 + github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 github.com/httprunner/funplugin v0.5.5 github.com/jinzhu/copier v0.3.5 @@ -82,7 +83,6 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/goph/emperror v0.17.2 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/grandcat/zeroconf v1.0.0 // indirect diff --git a/internal/version/VERSION b/internal/version/VERSION index 76fd650b..d827604c 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-250711 +v5.0.0-250716 diff --git a/uixt/sdk.go b/uixt/sdk.go index 8d105bbc..1bf4204a 100644 --- a/uixt/sdk.go +++ b/uixt/sdk.go @@ -151,7 +151,8 @@ func (dExt *XTDriver) ExecuteAction(ctx context.Context, action option.MobileAct // Execute via MCP tool result, err := dExt.client.CallTool(ctx, req) if err != nil { - return SessionData{}, fmt.Errorf("MCP tool call failed: %w", err) + // Notice: preserve the original error code + return SessionData{}, errors.Wrap(err, "call MCP tool failed") } // Check if the tool execution had business logic errors @@ -259,7 +260,7 @@ func (dExt *XTDriver) CallMCPTool(ctx context.Context, Str("server", serverName). Str("tool", toolName). Msg("call MCP tool failed") - return nil, err + return nil, errors.Wrap(err, "call MCP tool failed") } if result.IsError { From a3b55348cec15023704de9bccbfc656dce948bf1 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Wed, 16 Jul 2025 00:41:42 +0800 Subject: [PATCH 4/4] refactor: use DeviceHTTPDriverError when request driver failed --- uixt/driver_session.go | 23 ++++++----------------- uixt/ios_device.go | 3 +-- uixt/ios_driver_wda.go | 12 +++++------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/uixt/driver_session.go b/uixt/driver_session.go index ab837c9a..43bc1491 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -155,33 +155,21 @@ func (s *DriverSession) buildURL(urlStr string) (string, error) { } func (s *DriverSession) GET(urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { - rawResp, err = s.RequestWithRetry(http.MethodGet, urlStr, nil, opts...) - if err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) - } - return rawResp, nil + return s.RequestWithRetry(http.MethodGet, urlStr, nil, opts...) } func (s *DriverSession) POST(data interface{}, urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { var bsJSON []byte = nil if data != nil { if bsJSON, err = json.Marshal(data); err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + return nil, errors.Wrap(code.InvalidParamError, err.Error()) } } - rawResp, err = s.RequestWithRetry(http.MethodPost, urlStr, bsJSON, opts...) - if err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) - } - return rawResp, nil + return s.RequestWithRetry(http.MethodPost, urlStr, bsJSON, opts...) } func (s *DriverSession) DELETE(urlStr string, opts ...option.ActionOption) (rawResp DriverRawResponse, err error) { - rawResp, err = s.RequestWithRetry(http.MethodDelete, urlStr, nil, opts...) - if err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) - } - return rawResp, nil + return s.RequestWithRetry(http.MethodDelete, urlStr, nil, opts...) } func (s *DriverSession) RequestWithRetry(method string, urlStr string, rawBody []byte, opts ...option.ActionOption) ( @@ -205,7 +193,8 @@ func (s *DriverSession) RequestWithRetry(method string, urlStr string, rawBody [ return rawResp, nil } - lastError = err + // Notice: use DeviceHTTPDriverError when request driver failed + lastError = errors.Wrap(code.DeviceHTTPDriverError, err.Error()) log.Warn().Err(err).Msgf("request failed, attempt %d/%d", attempt, s.maxRetry) // If this was the last attempt, break diff --git a/uixt/ios_device.go b/uixt/ios_device.go index ba16502f..59d66258 100644 --- a/uixt/ios_device.go +++ b/uixt/ios_device.go @@ -231,8 +231,7 @@ func (dev *IOSDevice) NewDriver() (driver IDriver, err error) { if dev.Options.ResetHomeOnStartup { log.Info().Msg("go back to home screen") if err = wdaDriver.Home(); err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("go back to home screen failed: %v", err)) + return nil, errors.Wrap(err, "go back to home screen failed") } } if dev.Options.LogOn { diff --git a/uixt/ios_driver_wda.go b/uixt/ios_driver_wda.go index 2ca91d9f..724b1357 100644 --- a/uixt/ios_driver_wda.go +++ b/uixt/ios_driver_wda.go @@ -196,7 +196,7 @@ func (wd *WDADriver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) { // [[FBRoute GET:@"/wda/device/info"].withoutSession var rawResp DriverRawResponse if rawResp, err = wd.Session.GET("/wda/device/info"); err != nil { - return types.DeviceInfo{}, errors.Wrap(code.DeviceHTTPDriverError, err.Error()) + return types.DeviceInfo{}, err } reply := new(struct{ Value struct{ types.DeviceInfo } }) if err = json.Unmarshal(rawResp, reply); err != nil { @@ -298,12 +298,12 @@ func (wd *WDADriver) ScreenShot(opts ...option.ActionOption) (raw *bytes.Buffer, // [[FBRoute GET:@"/screenshot"].withoutSession respondWithTarget:self action:@selector(handleGetScreenshot:)] rawResp, err := wd.Session.GET("/screenshot") if err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, + return nil, errors.Wrap(code.DeviceScreenShotError, fmt.Sprintf("WDA screenshot failed %v", err)) } raw, err = rawResp.ValueDecodeAsBase64() if err != nil { - return nil, errors.Wrap(code.DeviceHTTPDriverError, + return nil, errors.Wrap(code.DeviceScreenShotError, fmt.Sprintf("decode WDA screenshot data failed: %v", err)) } return raw, nil @@ -454,8 +454,7 @@ func (wd *WDADriver) AppLaunch(bundleId string) (err error) { } _, err = wd.Session.POST(data, "/wings/apps/launch") if err != nil { - return errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("wda launch failed: %v", err)) + return errors.Wrap(err, "wda app launch failed") } return nil } @@ -466,8 +465,7 @@ func (wd *WDADriver) AppLaunchUnattached(bundleId string) (err error) { data := map[string]interface{}{"bundleId": bundleId} _, err = wd.Session.POST(data, "/wda/apps/launchUnattached") if err != nil { - return errors.Wrap(code.DeviceHTTPDriverError, - fmt.Sprintf("wda launchUnattached failed: %v", err)) + return errors.Wrap(err, "wda app launchUnattached failed") } return nil }