Procházet zdrojové kódy

feat: support detailed error message

Yeuoly před 10 měsíci
rodič
revize
952de7e4b8

+ 21 - 5
internal/core/plugin_daemon/generic.go

@@ -2,6 +2,7 @@ package plugin_daemon
 
 import (
 	"errors"
+	"fmt"
 
 	"github.com/langgenius/dify-plugin-daemon/internal/core/plugin_daemon/backwards_invocation"
 	"github.com/langgenius/dify-plugin-daemon/internal/core/plugin_daemon/backwards_invocation/transaction"
@@ -31,14 +32,22 @@ func GenericInvokePlugin[Req any, Rsp any](
 			chunk, err := parser.UnmarshalJsonBytes[Rsp](chunk.Data)
 			if err != nil {
 				log.Error("unmarshal json failed: %s", err.Error())
-				response.WriteError(err)
+				response.WriteError(errors.New(parser.MarshalJson(map[string]string{
+					"error_type": "unmarshal_error",
+					"message":    fmt.Sprintf("unmarshal json failed: %s", err.Error()),
+				})))
+				response.Close()
+				return
 			} else {
 				response.Write(chunk)
 			}
 		case plugin_entities.SESSION_MESSAGE_TYPE_INVOKE:
 			// check if the request contains a aws_event_id
 			if runtime.Type() == plugin_entities.PLUGIN_RUNTIME_TYPE_AWS {
-				response.WriteError(errors.New("aws event is not supported by full duplex"))
+				response.WriteError(errors.New(parser.MarshalJson(map[string]string{
+					"error_type": "aws_event_not_supported",
+					"message":    "aws event is not supported by full duplex",
+				})))
 				response.Close()
 				return
 			}
@@ -49,7 +58,11 @@ func GenericInvokePlugin[Req any, Rsp any](
 				transaction.NewFullDuplexEventWriter(session),
 				chunk.Data,
 			); err != nil {
-				log.Error("invoke dify failed: %s", err.Error())
+				response.WriteError(errors.New(parser.MarshalJson(map[string]string{
+					"error_type": "invoke_dify_error",
+					"message":    fmt.Sprintf("invoke dify failed: %s", err.Error()),
+				})))
+				response.Close()
 				return
 			}
 		case plugin_entities.SESSION_MESSAGE_TYPE_END:
@@ -59,10 +72,13 @@ func GenericInvokePlugin[Req any, Rsp any](
 			if err != nil {
 				break
 			}
-			response.WriteError(errors.New(e.Error))
+			response.WriteError(errors.New(e.Error()))
 			response.Close()
 		default:
-			response.WriteError(errors.New("unknown stream message type: " + string(chunk.Type)))
+			response.WriteError(errors.New(parser.MarshalJson(map[string]string{
+				"error_type": "unknown_stream_message_type",
+				"message":    "unknown stream message type: " + string(chunk.Type),
+			})))
 			response.Close()
 		}
 	})

+ 10 - 5
internal/core/plugin_manager/aws_manager/io.go

@@ -36,7 +36,8 @@ func (r *AWSPluginRuntime) Write(session_id string, data []byte) {
 		l.Send(plugin_entities.SessionMessage{
 			Type: plugin_entities.SESSION_MESSAGE_TYPE_ERROR,
 			Data: parser.MarshalJsonBytes(plugin_entities.ErrorResponse{
-				Error: fmt.Sprintf("Error creating request: %v", err),
+				ErrorType: "inner_error",
+				Message:   fmt.Sprintf("Error creating request: %v", err),
 			}),
 		})
 		l.Close()
@@ -72,7 +73,8 @@ func (r *AWSPluginRuntime) Write(session_id string, data []byte) {
 			l.Send(plugin_entities.SessionMessage{
 				Type: plugin_entities.SESSION_MESSAGE_TYPE_ERROR,
 				Data: parser.MarshalJsonBytes(plugin_entities.ErrorResponse{
-					Error: "failed to establish connection to plugin",
+					ErrorType: "inner_error",
+					Message:   fmt.Sprintf("Error sending request to aws lambda: %v", err),
 				}),
 			})
 			r.Error(fmt.Sprintf("Error sending request to aws lambda: %v", err))
@@ -96,7 +98,8 @@ func (r *AWSPluginRuntime) Write(session_id string, data []byte) {
 						l.Send(plugin_entities.SessionMessage{
 							Type: plugin_entities.SESSION_MESSAGE_TYPE_ERROR,
 							Data: parser.MarshalJsonBytes(plugin_entities.ErrorResponse{
-								Error: fmt.Sprintf("failed to parse session message %s, err: %v", bytes, err),
+								ErrorType: "inner_error",
+								Message:   fmt.Sprintf("failed to parse session message %s, err: %v", bytes, err),
 							}),
 						})
 						session_alive = false
@@ -108,7 +111,8 @@ func (r *AWSPluginRuntime) Write(session_id string, data []byte) {
 					l.Send(plugin_entities.SessionMessage{
 						Type: plugin_entities.SESSION_MESSAGE_TYPE_ERROR,
 						Data: parser.MarshalJsonBytes(plugin_entities.ErrorResponse{
-							Error: fmt.Sprintf("encountered an error: %v", err),
+							ErrorType: "inner_error",
+							Message:   fmt.Sprintf("encountered an error: %v", err),
 						}),
 					})
 				},
@@ -120,7 +124,8 @@ func (r *AWSPluginRuntime) Write(session_id string, data []byte) {
 			l.Send(plugin_entities.SessionMessage{
 				Type: plugin_entities.SESSION_MESSAGE_TYPE_ERROR,
 				Data: parser.MarshalJsonBytes(plugin_entities.ErrorResponse{
-					Error: fmt.Sprintf("failed to read response body: %v", scanner.Err()),
+					ErrorType: "inner_error",
+					Message:   fmt.Sprintf("failed to read response body: %v", scanner.Err()),
 				}),
 			})
 		}

+ 21 - 0
internal/types/entities/error.go

@@ -0,0 +1,21 @@
+package entities
+
+import "github.com/langgenius/dify-plugin-daemon/internal/utils/parser"
+
+type Error struct {
+	ErrorType string `json:"error_type"`
+	Message   string `json:"message"`
+	Args      any    `json:"args"`
+}
+
+func (e *Error) Error() string {
+	return parser.MarshalJson(e)
+}
+
+func NewError(error_type string, message string, args ...any) *Error {
+	return &Error{
+		ErrorType: error_type,
+		Message:   message,
+		Args:      args,
+	}
+}

+ 10 - 5
internal/types/entities/plugin_entities/event.go

@@ -83,11 +83,16 @@ const (
 	SESSION_MESSAGE_TYPE_INVOKE SESSION_MESSAGE_TYPE = "invoke"
 )
 
-type PluginResponseChunk struct {
-	Type string          `json:"type"`
-	Data json.RawMessage `json:"data"`
+type ErrorResponse struct {
+	Message   string         `json:"message"`
+	ErrorType string         `json:"error_type"`
+	Args      map[string]any `json:"args" validate:"omitempty,max=10"` // max 10 args
 }
 
-type ErrorResponse struct {
-	Error string `json:"error"`
+func (e *ErrorResponse) Error() string {
+	return parser.MarshalJson(map[string]any{
+		"message":    e.Message,
+		"error_type": e.ErrorType,
+		"args":       e.Args,
+	})
 }

+ 6 - 2
internal/types/entities/response.go

@@ -14,12 +14,16 @@ func NewSuccessResponse(data any) *Response {
 	}
 }
 
-func NewErrorResponse(code int, message string) *Response {
-	return &Response{
+func NewErrorResponse(code int, message string, args ...any) *Response {
+	resp := &Response{
 		Code:    code,
 		Message: message,
 		Data:    nil,
 	}
+	if len(args) > 0 {
+		resp.Data = args[0]
+	}
+	return resp
 }
 
 type GenericResponse[T any] struct {