refactor looker

This commit is contained in:
duwenxin
2026-02-04 01:31:13 -05:00
parent 2583c5adc9
commit 919787562a
14 changed files with 194 additions and 98 deletions

View File

@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,12 +17,14 @@ package cassandracql
import (
"context"
"fmt"
"net/http"
gocql "github.com/apache/cassandra-gocql-driver/v2"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -107,23 +109,27 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool {
}
// Invoke implements tools.Tool.
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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract template params %w", err)
return nil, util.NewAgentError("unable to extract template params", err)
}
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract standard params %w", err)
return nil, util.NewAgentError("unable to extract standard params", err)
}
return source.RunSQL(ctx, newStatement, newParams)
resp, err := source.RunSQL(ctx, newStatement, newParams)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
// Manifest implements tools.Tool.

View File

@@ -17,11 +17,13 @@ package clickhouse
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -87,18 +89,22 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token 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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
sql, ok := paramsMap["sql"].(string)
if !ok {
return nil, fmt.Errorf("unable to cast sql parameter %s", paramsMap["sql"])
return nil, util.NewAgentError(fmt.Sprintf("unable to cast sql parameter %s", paramsMap["sql"]), nil)
}
return source.RunSQL(ctx, sql, nil)
resp, err := source.RunSQL(ctx, sql, nil)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,11 +17,13 @@ package clickhouse
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -86,10 +88,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token 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", http.StatusInternalServerError, err)
}
// Query to list all databases
@@ -97,7 +99,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
out, err := source.RunSQL(ctx, query, nil)
if err != nil {
return nil, err
return nil, util.ProcessGeneralError(err)
}
return out, nil
@@ -129,4 +131,4 @@ func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string,
func (t Tool) GetParameters() parameters.Parameters {
return t.Parameters
}
}

View File

@@ -17,11 +17,13 @@ package clickhouse
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -90,34 +92,37 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token 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", http.StatusInternalServerError, err)
}
mapParams := params.AsMap()
database, ok := mapParams[databaseKey].(string)
if !ok {
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", databaseKey)
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", databaseKey), nil)
}
// Query to list all tables in the specified database
// Note: formatting identifier directly is risky if input is untrusted, but standard for this tool structure.
query := fmt.Sprintf("SHOW TABLES FROM %s", database)
out, err := source.RunSQL(ctx, query, nil)
if err != nil {
return nil, err
return nil, util.ProcessGeneralError(err)
}
res, ok := out.([]any)
if !ok {
return nil, fmt.Errorf("unable to convert result to list")
return nil, util.NewClientServerError("unable to convert result to list", http.StatusInternalServerError, nil)
}
var tables []map[string]any
for _, item := range res {
tableMap, ok := item.(map[string]any)
if !ok {
return nil, fmt.Errorf("unexpected type in result: got %T, want map[string]any", item)
return nil, util.NewClientServerError(fmt.Sprintf("unexpected type in result: got %T, want map[string]any", item), http.StatusInternalServerError, nil)
}
tableMap["database"] = database
tables = append(tables, tableMap)

View File

@@ -17,11 +17,13 @@ package clickhouse
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -88,24 +90,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token 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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract template params: %w", err)
return nil, util.NewAgentError("unable to extract template params", err)
}
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract standard params: %w", err)
return nil, util.NewAgentError("unable to extract standard params", err)
}
return source.RunSQL(ctx, newStatement, newParams)
resp, err := source.RunSQL(ctx, newStatement, newParams)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,12 +17,14 @@ package couchbase
import (
"context"
"fmt"
"net/http"
"github.com/couchbase/gocb/v2"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -58,7 +60,6 @@ type Config struct {
TemplateParameters parameters.Parameters `yaml:"templateParameters"`
}
// validate interface
var _ tools.ToolConfig = Config{}
func (cfg Config) ToolConfigType() string {
@@ -72,7 +73,6 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
}
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, allParameters, nil)
// finish tool setup
t := Tool{
Config: cfg,
AllParams: allParameters,
@@ -82,7 +82,6 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
return t, nil
}
// validate interface
var _ tools.Tool = Tool{}
type Tool struct {
@@ -96,23 +95,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
namedParamsMap := params.AsMap()
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, namedParamsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract template params %w", err)
return nil, util.NewAgentError("unable to extract template params", err)
}
newParams, err := parameters.GetParams(t.Parameters, namedParamsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract standard params %w", err)
return nil, util.NewAgentError("unable to extract standard params", err)
}
return source.RunSQL(newStatement, newParams)
resp, err := source.RunSQL(newStatement, newParams)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -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"
)
@@ -86,18 +87,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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) {
paramsMap := params.AsMap()
projectDir, ok := paramsMap["project_dir"].(string)
if !ok || projectDir == "" {
return nil, fmt.Errorf("error casting 'project_dir' to string or invalid value")
return nil, util.NewAgentError("error casting 'project_dir' to string or invalid value", nil)
}
cmd := exec.CommandContext(ctx, "dataform", "compile", projectDir, "--json")
output, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("error executing dataform compile: %w\nOutput: %s", err, string(output))
// Compilation failures are considered AgentErrors (invalid user code/project)
return nil, util.NewAgentError(fmt.Sprintf("error executing dataform compile: %v\nOutput: %s", err, string(output)), err)
}
return strings.TrimSpace(string(output)), nil

View File

@@ -17,12 +17,14 @@ package dgraph
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/sources/dgraph"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -91,12 +93,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
return source.RunSQL(t.Statement, params, t.IsQuery, t.Timeout)
resp, err := source.RunSQL(t.Statement, params, t.IsQuery, t.Timeout)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
@@ -125,4 +131,4 @@ func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string,
func (t Tool) GetParameters() parameters.Parameters {
return t.Parameters
}
}

View File

@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
@@ -90,25 +91,30 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
sql, ok := paramsMap["sql"].(string)
sqlStr, ok := paramsMap["sql"].(string)
if !ok {
return nil, fmt.Errorf("unable to get cast %s", paramsMap["sql"])
return nil, util.NewAgentError(fmt.Sprintf("unable to cast parameter 'sql' to string: %v", paramsMap["sql"]), nil)
}
// Log the query executed for debugging.
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("error getting logger: %s", err)
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
}
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
return source.RunSQL(ctx, sql, nil)
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sqlStr))
resp, err := source.RunSQL(ctx, sqlStr, nil)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -18,12 +18,14 @@ import (
"context"
"database/sql"
"fmt"
"net/http"
"strings"
"github.com/goccy/go-yaml"
"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"
)
@@ -98,21 +100,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
statement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract template params: %w", err)
return nil, util.NewAgentError("unable to extract template params", err)
}
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
if err != nil {
return nil, fmt.Errorf("unable to extract standard params: %w", err)
return nil, util.NewAgentError("unable to extract standard params", err)
}
namedArgs := make([]any, 0, len(newParams))
@@ -127,7 +129,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
namedArgs = append(namedArgs, value)
}
}
return source.RunSQL(ctx, statement, namedArgs)
resp, err := source.RunSQL(ctx, statement, namedArgs)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,18 +17,18 @@ import (
"bytes"
"context"
"fmt"
"maps"
"net/http"
"net/url"
"slices"
"strings"
"maps"
"text/template"
yaml "github.com/goccy/go-yaml"
"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"
)
@@ -226,10 +226,10 @@ func getHeaders(headerParams parameters.Parameters, defaultHeaders map[string]st
return allHeaders, nil
}
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", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
@@ -237,27 +237,35 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Calculate request body
requestBody, err := getRequestBody(t.BodyParams, t.RequestBody, paramsMap)
if err != nil {
return nil, fmt.Errorf("error populating request body: %s", err)
return nil, util.NewAgentError("error populating request body", err)
}
// Calculate URL
urlString, err := getURL(source.HttpBaseURL(), t.Path, t.PathParams, t.QueryParams, source.HttpQueryParams(), paramsMap)
if err != nil {
return nil, fmt.Errorf("error populating path parameters: %s", err)
return nil, util.NewAgentError("error populating path parameters", err)
}
req, _ := http.NewRequest(string(t.Method), urlString, strings.NewReader(requestBody))
req, err := http.NewRequestWithContext(ctx, string(t.Method), urlString, strings.NewReader(requestBody))
if err != nil {
return nil, util.NewClientServerError("error creating http request", http.StatusInternalServerError, err)
}
// Calculate request headers
allHeaders, err := getHeaders(t.HeaderParams, t.Headers, paramsMap)
if err != nil {
return nil, fmt.Errorf("error populating request headers: %s", err)
return nil, util.NewAgentError("error populating request headers", err)
}
// Set request headers
for k, v := range allHeaders {
req.Header.Set(k, v)
}
return source.RunRequest(req)
resp, err := source.RunRequest(req)
if err != nil {
return nil, util.ProcessGeneralError(err)
}
return resp, nil
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -16,6 +16,7 @@ package lookeradddashboardelement
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
@@ -134,58 +135,74 @@ var (
visType string = "vis"
)
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", http.StatusInternalServerError, err)
}
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
return nil, util.NewClientServerError("unable to get logger from ctx", http.StatusInternalServerError, err)
}
logger.DebugContext(ctx, "params = ", params)
wq, err := lookercommon.ProcessQueryArgs(ctx, params)
if err != nil {
return nil, fmt.Errorf("error building query request: %w", err)
return nil, util.NewAgentError("error building query request", err)
}
paramsMap := params.AsMap()
dashboard_id := paramsMap["dashboard_id"].(string)
title := paramsMap["title"].(string)
visConfig := paramsMap["vis_config"].(map[string]any)
dashboard_id, ok := paramsMap["dashboard_id"].(string)
if !ok {
return nil, util.NewAgentError("dashboard_id parameter missing or invalid", nil)
}
title, ok := paramsMap["title"].(string)
if !ok {
title = ""
}
visConfig, ok := paramsMap["vis_config"].(map[string]any)
if !ok {
visConfig = make(map[string]any)
}
wq.VisConfig = &visConfig
sdk, err := source.GetLookerSDK(string(accessToken))
if err != nil {
return nil, fmt.Errorf("error getting sdk: %w", err)
return nil, util.NewClientServerError("error getting sdk", http.StatusInternalServerError, err)
}
qresp, err := sdk.CreateQuery(*wq, "id", source.LookerApiSettings())
if err != nil {
return nil, fmt.Errorf("error making create query request: %w", err)
return nil, util.ProcessGeneralError(err)
}
dashFilters := []any{}
if v, ok := paramsMap["dashboard_filters"]; ok {
if v != nil {
dashFilters = paramsMap["dashboard_filters"].([]any)
if df, ok := v.([]any); ok {
dashFilters = df
}
}
}
var filterables []v4.ResultMakerFilterables
for _, m := range dashFilters {
f := m.(map[string]any)
f, ok := m.(map[string]any)
if !ok {
return nil, util.NewAgentError("invalid dashboard filter structure", nil)
}
name, ok := f["dashboard_filter_name"].(string)
if !ok {
return nil, fmt.Errorf("error processing dashboard filter: %w", err)
return nil, util.NewAgentError("error processing dashboard filter: missing dashboard_filter_name", nil)
}
field, ok := f["field"].(string)
if !ok {
return nil, fmt.Errorf("error processing dashboard filter: %w", err)
return nil, util.NewAgentError("error processing dashboard filter: missing field", nil)
}
listener := v4.ResultMakerFilterablesListen{
DashboardFilterName: &name,
@@ -233,7 +250,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
resp, err := sdk.CreateDashboardElement(req, source.LookerApiSettings())
if err != nil {
return nil, fmt.Errorf("error making create dashboard element request: %w", err)
return nil, util.ProcessGeneralError(err)
}
logger.DebugContext(ctx, "resp = %v", resp)

View File

@@ -16,6 +16,7 @@ package lookeradddashboardfilter
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
@@ -128,33 +129,54 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
return nil, util.NewClientServerError("unable to get logger from ctx", http.StatusInternalServerError, err)
}
logger.DebugContext(ctx, "params = ", params)
paramsMap := params.AsMap()
dashboard_id := paramsMap["dashboard_id"].(string)
name := paramsMap["name"].(string)
title := paramsMap["title"].(string)
filterType := paramsMap["filter_type"].(string)
dashboard_id, ok := paramsMap["dashboard_id"].(string)
if !ok {
return nil, util.NewAgentError("dashboard_id parameter missing or invalid", nil)
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError("name parameter missing or invalid", nil)
}
title, ok := paramsMap["title"].(string)
if !ok {
return nil, util.NewAgentError("title parameter missing or invalid", nil)
}
filterType, ok := paramsMap["filter_type"].(string)
if !ok {
return nil, util.NewAgentError("filter_type parameter missing or invalid", nil)
}
switch filterType {
case "date_filter":
case "number_filter":
case "string_filter":
case "field_filter":
default:
return nil, fmt.Errorf("invalid filter type: %s. Must be one of date_filter, number_filter, string_filter, field_filter", filterType)
return nil, util.NewAgentError(fmt.Sprintf("invalid filter type: %s. Must be one of date_filter, number_filter, string_filter, field_filter", filterType), nil)
}
allowMultipleValues, ok := paramsMap["allow_multiple_values"].(bool)
if !ok {
// defaults should handle this, but safe fallback
allowMultipleValues = true
}
required, ok := paramsMap["required"].(bool)
if !ok {
required = false
}
allowMultipleValues := paramsMap["allow_multiple_values"].(bool)
required := paramsMap["required"].(bool)
req := v4.WriteCreateDashboardFilter{
DashboardId: dashboard_id,
@@ -165,9 +187,8 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
Required: &required,
}
if v, ok := paramsMap["default_value"]; ok {
if v != nil {
defaultValue := paramsMap["default_value"].(string)
if v, ok := paramsMap["default_value"]; ok && v != nil {
if defaultValue, ok := v.(string); ok {
req.DefaultValue = &defaultValue
}
}
@@ -175,15 +196,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if filterType == "field_filter" {
model, ok := paramsMap["model"].(string)
if !ok || model == "" {
return nil, fmt.Errorf("model must be specified for field_filter type")
return nil, util.NewAgentError("model must be specified for field_filter type", nil)
}
explore, ok := paramsMap["explore"].(string)
if !ok || explore == "" {
return nil, fmt.Errorf("explore must be specified for field_filter type")
return nil, util.NewAgentError("explore must be specified for field_filter type", nil)
}
dimension, ok := paramsMap["dimension"].(string)
if !ok || dimension == "" {
return nil, fmt.Errorf("dimension must be specified for field_filter type")
return nil, util.NewAgentError("dimension must be specified for field_filter type", nil)
}
req.Model = &model
@@ -193,12 +214,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
sdk, err := source.GetLookerSDK(string(accessToken))
if err != nil {
return nil, fmt.Errorf("error getting sdk: %w", err)
return nil, util.NewClientServerError("error getting sdk", http.StatusInternalServerError, err)
}
resp, err := sdk.CreateDashboardFilter(req, "name", source.LookerApiSettings())
if err != nil {
return nil, fmt.Errorf("error making create dashboard filter request: %s", err)
return nil, util.ProcessGeneralError(err)
}
logger.DebugContext(ctx, "resp = %v", resp)

View File

@@ -215,10 +215,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
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", http.StatusInternalServerError, err)
}
var tokenStr string
@@ -226,11 +226,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Get credentials for the API call
// Use cloud-platform token source for Gemini Data Analytics API
if t.TokenSource == nil {
return nil, fmt.Errorf("cloud-platform token source is missing")
return nil, util.NewClientServerError("cloud-platform token source is missing", http.StatusInternalServerError, nil)
}
token, err := t.TokenSource.Token()
if err != nil {
return nil, fmt.Errorf("failed to get token from cloud-platform token source: %w", err)
return nil, util.NewClientServerError("failed to get token from cloud-platform token source", http.StatusInternalServerError, err)
}
tokenStr = token.AccessToken
@@ -286,7 +286,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Call the streaming API
response, err := getStream(ctx, caURL, payload, headers)
if err != nil {
return nil, fmt.Errorf("failed to get response from conversational analytics API: %w", err)
return nil, util.NewClientServerError("failed to get response from conversational analytics API", http.StatusInternalServerError, err)
}
return response, nil