diff --git a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go index db59b982a8..d0b249581a 100644 --- a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go +++ b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -122,44 +123,49 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) if !ok || project == "" { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string") } location, ok := paramsMap["location"].(string) if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + return nil, util.NewAgentError("invalid 'location' parameter; expected a string") } clusterID, ok := paramsMap["cluster"].(string) if !ok || clusterID == "" { - return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string") } password, ok := paramsMap["password"].(string) if !ok || password == "" { - return nil, fmt.Errorf("invalid or missing 'password' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'password' parameter; expected a non-empty string") } network, ok := paramsMap["network"].(string) if !ok { - return nil, fmt.Errorf("invalid 'network' parameter; expected a string") + return nil, util.NewAgentError("invalid 'network' parameter; expected a string") } user, ok := paramsMap["user"].(string) if !ok { - return nil, fmt.Errorf("invalid 'user' parameter; expected a string") + return nil, util.NewAgentError("invalid 'user' parameter; expected a string", nil) + } + resp, err := source.CreateCluster(ctx, project, location, network, user, password, clusterID, string(accessToken)) + + if err != nil { + return nil, util.ProecessGcpError(err) } - return source.CreateCluster(ctx, project, location, network, user, password, clusterID, string(accessToken)) + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go index 8b0adc3646..62cc691399 100644 --- a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go +++ b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -123,36 +124,36 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) if !ok || project == "" { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil) } location, ok := paramsMap["location"].(string) if !ok || location == "" { - return nil, fmt.Errorf("invalid or missing 'location' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a non-empty string", nil) } cluster, ok := paramsMap["cluster"].(string) if !ok || cluster == "" { - return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil) } instanceID, ok := paramsMap["instance"].(string) if !ok || instanceID == "" { - return nil, fmt.Errorf("invalid or missing 'instance' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a non-empty string", nil) } instanceType, ok := paramsMap["instanceType"].(string) if !ok || (instanceType != "READ_POOL" && instanceType != "PRIMARY") { - return nil, fmt.Errorf("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'") + return nil, util.NewAgentError("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'", nil) } displayName, _ := paramsMap["displayName"].(string) @@ -161,11 +162,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if instanceType == "READ_POOL" { nodeCount, ok = paramsMap["nodeCount"].(int) if !ok { - return nil, fmt.Errorf("invalid 'nodeCount' parameter; expected an integer for READ_POOL") + return nil, util.NewAgentError("invalid 'nodeCount' parameter; expected an integer for READ_POOL", nil) } } - return source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken)) + resp, err := source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go index f1c0cb7c64..45a9afc77f 100644 --- a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go +++ b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -122,43 +123,43 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) if !ok || project == "" { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string") } location, ok := paramsMap["location"].(string) if !ok || location == "" { - return nil, fmt.Errorf("invalid or missing'location' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing'location' parameter; expected a non-empty string") } cluster, ok := paramsMap["cluster"].(string) if !ok || cluster == "" { - return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string") } userID, ok := paramsMap["user"].(string) if !ok || userID == "" { - return nil, fmt.Errorf("invalid or missing 'user' parameter; expected a non-empty string") + return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a non-empty string") } userType, ok := paramsMap["userType"].(string) if !ok || (userType != "ALLOYDB_BUILT_IN" && userType != "ALLOYDB_IAM_USER") { - return nil, fmt.Errorf("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'") + return nil, util.NewAgentError("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'") } var password string if userType == "ALLOYDB_BUILT_IN" { password, ok = paramsMap["password"].(string) if !ok || password == "" { - return nil, fmt.Errorf("password is required when userType is ALLOYDB_BUILT_IN") + return nil, util.NewAgentError("password is required when userType is ALLOYDB_BUILT_IN") } } @@ -170,7 +171,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para } } } - return source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID) + resp, err := source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go index d0dc9d7269..66273f2363 100644 --- a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go +++ b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -120,28 +121,32 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + if !ok || location == "" { + return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string") } cluster, ok := paramsMap["cluster"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string") + if !ok || cluster == "" { + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string") } - return source.GetCluster(ctx, project, location, cluster, string(accessToken)) + resp, err := source.GetCluster(ctx, project, location, cluster, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go index 569d7dda70..a1ce55df29 100644 --- a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go +++ b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -120,32 +121,36 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + if !ok || location == "" { + return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string") } cluster, ok := paramsMap["cluster"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string") + if !ok || cluster == "" { + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string") } instance, ok := paramsMap["instance"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'instance' parameter; expected a string") + if !ok || instance == "" { + return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a string") } - return source.GetInstance(ctx, project, location, cluster, instance, string(accessToken)) + resp, err := source.GetInstance(ctx, project, location, cluster, instance, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go index 9b9d532a6c..8142e74deb 100644 --- a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go +++ b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -120,32 +121,36 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + if !ok || location == "" { + return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string") } cluster, ok := paramsMap["cluster"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string") + if !ok || cluster == "" { + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string") } user, ok := paramsMap["user"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'user' parameter; expected a string") + if !ok || user == "" { + return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a string") } - return source.GetUsers(ctx, project, location, cluster, user, string(accessToken)) + resp, err := source.GetUsers(ctx, project, location, cluster, user, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go index 0477d05d55..c7cb6223e5 100644 --- a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go +++ b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -118,24 +119,28 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + return nil, util.NewAgentError("invalid 'location' parameter; expected a string") } - return source.ListCluster(ctx, project, location, string(accessToken)) + resp, err := source.ListCluster(ctx, project, location, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go index 749bdd5ea4..c0fc524bf0 100644 --- a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go +++ b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -119,28 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + return nil, util.NewAgentError("invalid 'location' parameter; expected a string") } cluster, ok := paramsMap["cluster"].(string) if !ok { - return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string") + return nil, util.NewAgentError("invalid 'cluster' parameter; expected a string") } - return source.ListInstance(ctx, project, location, cluster, string(accessToken)) + resp, err := source.ListInstance(ctx, project, location, cluster, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydblistusers/alloydblistusers.go b/internal/tools/alloydb/alloydblistusers/alloydblistusers.go index cbcc1a545c..d891d9a16d 100644 --- a/internal/tools/alloydb/alloydblistusers/alloydblistusers.go +++ b/internal/tools/alloydb/alloydblistusers/alloydblistusers.go @@ -22,6 +22,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -119,28 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) - if !ok { - return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string") + if !ok || project == "" { + return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string") } location, ok := paramsMap["location"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'location' parameter; expected a string") + if !ok || location == "" { + return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string") } cluster, ok := paramsMap["cluster"].(string) - if !ok { - return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string") + if !ok || cluster == "" { + return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string") } - return source.ListUsers(ctx, project, location, cluster, string(accessToken)) + resp, err := source.ListUsers(ctx, project, location, cluster, string(accessToken)) + if err != nil { + return nil, util.ProecessGcpError(err) + } + return resp, nil } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go index 8f10fed7e3..a4fe4f84e2 100644 --- a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go +++ b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go @@ -24,6 +24,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/tools" + "github.com/googleapis/genai-toolbox/internal/util" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -213,25 +214,25 @@ func (t Tool) ToConfig() tools.ToolConfig { } // Invoke executes the tool's logic. -func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { +func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { - return nil, err + return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) if !ok { - return nil, fmt.Errorf("missing 'project' parameter") + return nil, util.NewAgentError("missing 'project' parameter") } location, ok := paramsMap["location"].(string) if !ok { - return nil, fmt.Errorf("missing 'location' parameter") + return nil, util.NewAgentError("missing 'location' parameter") } operation, ok := paramsMap["operation"].(string) if !ok { - return nil, fmt.Errorf("missing 'operation' parameter") + return nil, util.NewAgentError("missing 'operation' parameter") } ctx, cancel := context.WithTimeout(ctx, 30*time.Minute) @@ -246,14 +247,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para for retries < maxRetries { select { case <-ctx.Done(): - return nil, fmt.Errorf("timed out waiting for operation: %w", ctx.Err()) + return nil, util.NewAgentError("timed out waiting for operation %s", ctx.Err()) default: } op, err := source.GetOperations(ctx, project, location, operation, alloyDBConnectionMessageTemplate, delay, string(accessToken)) if err != nil { - return nil, err - } else if op != nil { + return nil, util.ProecessGcpError(err) + } + if op != nil { return op, nil } @@ -264,7 +266,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para } retries++ } - return nil, fmt.Errorf("exceeded max retries waiting for operation") + return nil, util.NewAgentError("exceeded max retries waiting for operation") } func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) { diff --git a/internal/tools/tools.go b/internal/tools/tools.go index 81a023cb66..93f2654c85 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -87,7 +87,7 @@ func (token AccessToken) ParseBearerToken() (string, error) { } type Tool interface { - Invoke(context.Context, SourceProvider, parameters.ParamValues, AccessToken) (any, error) + Invoke(context.Context, SourceProvider, parameters.ParamValues, AccessToken) (any, util.ToolboxError) EmbedParams(context.Context, parameters.ParamValues, map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) Manifest() Manifest McpManifest() McpManifest diff --git a/internal/util/errors.go b/internal/util/errors.go index 38dd7f5954..96cc98a70d 100644 --- a/internal/util/errors.go +++ b/internal/util/errors.go @@ -12,7 +12,13 @@ // limitations under the License. package util -import "fmt" +import ( + "errors" + "fmt" + "net/http" + + "google.golang.org/api/googleapi" +) type ErrorCategory string @@ -75,3 +81,24 @@ func (e *ClientServerError) Unwrap() error { return e.Cause } func NewClientServerError(msg string, code int, cause error) *ClientServerError { return &ClientServerError{Msg: msg, Code: code, Cause: cause} } + +func ProecessGcpError(err error) ToolboxError { + var gErr *googleapi.Error + if errors.As(err, &gErr) { + if gErr.Code == 401 { + return NewClientServerError( + "failed to access GCP resource", + http.StatusUnauthorized, + err, + ) + } + if gErr.Code == 403 { + return NewClientServerError( + "failed to access GCP resource", + http.StatusForbidden, + err, + ) + } + } + return NewAgentError("error processing GCP request", err) +}