diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27b829148dc4..712f7aa71c8b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,11 +92,11 @@ implementation](https://github.com/googleapis/genai-toolbox/blob/main/internal/s `newdb.go`. Create a `Config` struct to include all the necessary parameters for connecting to the database (e.g., host, port, username, password, database name) and a `Source` struct to store necessary parameters for tools (e.g., - Name, Kind, connection object, additional config). + Name, Type, connection object, additional config). * **Implement the [`SourceConfig`](https://github.com/googleapis/genai-toolbox/blob/fd300dc606d88bf9f7bba689e2cee4e3565537dd/internal/sources/sources.go#L57) interface**. This interface requires two methods: - * `SourceConfigKind() string`: Returns a unique string identifier for your + * `SourceConfigType() string`: Returns a unique string identifier for your data source (e.g., `"newdb"`). * `Initialize(ctx context.Context, tracer trace.Tracer) (Source, error)`: Creates a new instance of your data source and establishes a connection to @@ -104,7 +104,7 @@ implementation](https://github.com/googleapis/genai-toolbox/blob/main/internal/s * **Implement the [`Source`](https://github.com/googleapis/genai-toolbox/blob/fd300dc606d88bf9f7bba689e2cee4e3565537dd/internal/sources/sources.go#L63) interface**. This interface requires one method: - * `SourceKind() string`: Returns the same string identifier as `SourceConfigKind()`. + * `SourceType() string`: Returns the same string identifier as `SourceConfigType()`. * **Implement `init()`** to register the new Source. * **Implement Unit Tests** in a file named `newdb_test.go`. @@ -126,7 +126,7 @@ tools. * **Implement the [`ToolConfig`](https://github.com/googleapis/genai-toolbox/blob/fd300dc606d88bf9f7bba689e2cee4e3565537dd/internal/tools/tools.go#L61) interface**. This interface requires one method: - * `ToolConfigKind() string`: Returns a unique string identifier for your tool + * `ToolConfigType() string`: Returns a unique string identifier for your tool (e.g., `"newdb-tool"`). * `Initialize(sources map[string]Source) (Tool, error)`: Creates a new instance of your tool and validates that it can connect to the specified @@ -243,7 +243,7 @@ resources. | style | Update src code, with only formatting and whitespace updates (e.g. code formatter or linter changes). | Pull requests should always add scope whenever possible. The scope is - formatted as `/` (e.g., `sources/postgres`, or + formatted as `/` (e.g., `sources/postgres`, or `tools/mssql-sql`). Ideally, **each PR covers only one scope**, if this is diff --git a/DEVELOPER.md b/DEVELOPER.md index ce9f8270701f..9836d6c9be41 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -47,12 +47,13 @@ Before you begin, ensure you have the following: ### Tool Naming Conventions This section details the purpose and conventions for MCP Toolbox's tools naming -properties, **tool name** and **tool kind**. +properties, **tool name** and **tool type**. ``` -cancel_hotel: <- tool name - kind: postgres-sql <- tool kind - source: my_pg_source +kind: tools +name: cancel_hotel <- tool name +type: postgres-sql <- tool type +source: my_pg_source ``` #### Tool Name @@ -76,17 +77,17 @@ The following guidelines apply to tool names: to a function) until they can be validated through extensive testing to ensure they do not negatively impact agent's performances. -#### Tool Kind +#### Tool Type -Tool kind serves as a category or type that a user can assign to a tool. +Tool type serves as a category or type that a user can assign to a tool. -The following guidelines apply to tool kinds: +The following guidelines apply to tool types: -* Should user hyphens over underscores (e.g. `firestore-list-collections` or +* Should use hyphens over underscores (e.g. `firestore-list-collections` or `firestore_list_colelctions`). * Should use product name in name (e.g. `firestore-list-collections` over `list-collections`). -* Changes to tool kind are breaking changes and should be avoided. +* Changes to tool type are breaking changes and should be avoided. ## Testing diff --git a/README.md b/README.md index 7cf3ca926792..f0443e4a805a 100644 --- a/README.md +++ b/README.md @@ -940,14 +940,14 @@ Toolbox should have access to. Most tools will have at least one source to execute against. ```yaml -sources: - my-pg-source: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: toolbox_db - user: toolbox_user - password: my-password +kind: sources +name: my-pg-source +type: postgres +host: 127.0.0.1 +port: 5432 +database: toolbox_db +user: toolbox_user +password: my-password ``` For more details on configuring different types of sources, see the @@ -956,19 +956,19 @@ For more details on configuring different types of sources, see the ### Tools The `tools` section of a `tools.yaml` define the actions an agent can take: what -kind of tool it is, which source(s) it affects, what parameters it uses, etc. +type of tool it is, which source(s) it affects, what parameters it uses, etc. ```yaml -tools: - search-hotels-by-name: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; +kind: tools +name: search-hotels-by-name +type: postgres-sql +source: my-pg-source +description: Search for hotels based on name. +parameters: + - name: name + type: string + description: The name of the hotel. +statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; ``` For more details on configuring different types of tools, see the diff --git a/cmd/root.go b/cmd/root.go index dfac1c250f2b..ce32662cea8e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,6 +15,7 @@ package cmd import ( + "bytes" "context" _ "embed" "fmt" @@ -396,7 +397,6 @@ func NewCommand(opts ...Option) *Command { type ToolsFile struct { Sources server.SourceConfigs `yaml:"sources"` - AuthSources server.AuthServiceConfigs `yaml:"authSources"` // Deprecated: Kept for compatibility. AuthServices server.AuthServiceConfigs `yaml:"authServices"` EmbeddingModels server.EmbeddingModelConfigs `yaml:"embeddingModels"` Tools server.ToolConfigs `yaml:"tools"` @@ -427,6 +427,129 @@ func parseEnv(input string) (string, error) { return output, err } +func convertToolsFile(raw []byte) ([]byte, error) { + var input yaml.MapSlice + decoder := yaml.NewDecoder(bytes.NewReader(raw), yaml.UseOrderedMap()) + + // convert to tools file v2 + var buf bytes.Buffer + encoder := yaml.NewEncoder(&buf) + + v1keys := []string{"sources", "authSources", "authServices", "embeddingModels", "tools", "toolsets", "prompts"} + for { + if err := decoder.Decode(&input); err != nil { + if err == io.EOF { + break + } + return nil, err + } + for _, item := range input { + key, ok := item.Key.(string) + if !ok { + return nil, fmt.Errorf("unexpected non-string key in input: %v", item.Key) + } + // check if the key is config file v1's key + if slices.Contains(v1keys, key) { + // check if value conversion to yaml.MapSlice successfully + // fields such as "tools" in toolsets might pass the first check but + // fail to convert to MapSlice + if slice, ok := item.Value.(yaml.MapSlice); ok { + // Deprecated: convert authSources to authServices + if key == "authSources" { + key = "authServices" + } + transformed, err := transformDocs(key, slice) + if err != nil { + return nil, err + } + // encode per-doc + for _, doc := range transformed { + if err := encoder.Encode(doc); err != nil { + return nil, err + } + } + } else { + // invalid input will be ignored + // we don't want to throw error here since the config could + // be valid but with a different order such as: + // --- + // tools: + // - tool_a + // kind: toolsets + // --- + continue + } + } else { + // this doc is already v2, encode to buf + if err := encoder.Encode(input); err != nil { + return nil, err + } + break + } + } + } + return buf.Bytes(), nil +} + +// transformDocs transforms the configuration file from v1 format to v2 +// yaml.MapSlice will preserve the order in a map +func transformDocs(kind string, input yaml.MapSlice) ([]yaml.MapSlice, error) { + var transformed []yaml.MapSlice + for _, entry := range input { + entryName, ok := entry.Key.(string) + if !ok { + return nil, fmt.Errorf("unexpected non-string key for entry in '%s': %v", kind, entry.Key) + } + entryBody := ProcessValue(entry.Value, kind == "toolsets") + + currentTransformed := yaml.MapSlice{ + {Key: "kind", Value: kind}, + {Key: "name", Value: entryName}, + } + + // Merge the transformed body into our result + if bodySlice, ok := entryBody.(yaml.MapSlice); ok { + currentTransformed = append(currentTransformed, bodySlice...) + } else { + return nil, fmt.Errorf("unable to convert entryBody to MapSlice") + } + transformed = append(transformed, currentTransformed) + } + return transformed, nil +} + +// ProcessValue recursively looks for MapSlices to rename 'kind' -> 'type' +func ProcessValue(v any, isToolset bool) any { + switch val := v.(type) { + case yaml.MapSlice: + // creating a new MapSlice is safer for recursive transformation + newVal := make(yaml.MapSlice, len(val)) + for i, item := range val { + // Perform renaming + if item.Key == "kind" { + item.Key = "type" + } + // Recursive call for nested values (e.g., nested objects or lists) + item.Value = ProcessValue(item.Value, false) + newVal[i] = item + } + return newVal + case []any: + // Process lists: If it's a toolset top-level list, wrap it. + if isToolset { + return yaml.MapSlice{{Key: "tools", Value: val}} + } + // Otherwise, recurse into list items (to catch nested objects) + newVal := make([]any, len(val)) + for i := range val { + newVal[i] = ProcessValue(val[i], false) + } + return newVal + default: + return val + } +} + // parseToolsFile parses the provided yaml into appropriate configs. func parseToolsFile(ctx context.Context, raw []byte) (ToolsFile, error) { var toolsFile ToolsFile @@ -437,8 +560,13 @@ func parseToolsFile(ctx context.Context, raw []byte) (ToolsFile, error) { } raw = []byte(output) + raw, err = convertToolsFile(raw) + if err != nil { + return toolsFile, fmt.Errorf("error converting tools file: %s", err) + } + // Parse contents - err = yaml.UnmarshalContext(ctx, raw, &toolsFile, yaml.Strict()) + toolsFile.Sources, toolsFile.AuthServices, toolsFile.EmbeddingModels, toolsFile.Tools, toolsFile.Toolsets, toolsFile.Prompts, err = server.UnmarshalResourceConfig(ctx, raw) if err != nil { return toolsFile, err } @@ -470,18 +598,6 @@ func mergeToolsFiles(files ...ToolsFile) (ToolsFile, error) { } } - // Check for conflicts and merge authSources (deprecated, but still support) - for name, authSource := range file.AuthSources { - if _, exists := merged.AuthSources[name]; exists { - conflicts = append(conflicts, fmt.Sprintf("authSource '%s' (file #%d)", name, fileIndex+1)) - } else { - if merged.AuthSources == nil { - merged.AuthSources = make(server.AuthServiceConfigs) - } - merged.AuthSources[name] = authSource - } - } - // Check for conflicts and merge authServices for name, authService := range file.AuthServices { if _, exists := merged.AuthServices[name]; exists { @@ -965,20 +1081,6 @@ func run(cmd *Command) error { cmd.cfg.ToolsetConfigs = finalToolsFile.Toolsets cmd.cfg.PromptConfigs = finalToolsFile.Prompts - authSourceConfigs := finalToolsFile.AuthSources - if authSourceConfigs != nil { - cmd.logger.WarnContext(ctx, "`authSources` is deprecated, use `authServices` instead") - - for k, v := range authSourceConfigs { - if _, exists := cmd.cfg.AuthServiceConfigs[k]; exists { - errMsg := fmt.Errorf("resource conflict detected: authSource '%s' has the same name as an existing authService. Please rename your authSource", k) - cmd.logger.ErrorContext(ctx, errMsg.Error()) - return errMsg - } - cmd.cfg.AuthServiceConfigs[k] = v - } - } - instrumentation, err := telemetry.CreateTelemetryInstrumentation(versionString) if err != nil { errMsg := fmt.Errorf("unable to create telemetry instrumentation: %w", err) diff --git a/cmd/root_test.go b/cmd/root_test.go index 17058d18ff6f..c69399a8003b 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -514,6 +514,437 @@ func TestDefaultLogLevel(t *testing.T) { } } +func TestConvertToolsFile(t *testing.T) { + tcs := []struct { + desc string + in string + want string + isErr bool + errStr string + }{ + { + desc: "basic convert", + in: ` + sources: + my-pg-instance: + kind: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + authServices: + my-google-auth: + kind: google + clientId: testing-id + tools: + example_tool: + kind: postgres-sql + source: my-pg-instance + description: some description + statement: SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + toolsets: + example_toolset: + - example_tool + prompts: + code_review: + description: ask llm to analyze code quality + messages: + - content: "please review the following code for quality: {{.code}}" + arguments: + - name: code + description: the code to review + embeddingModels: + gemini-model: + kind: gemini + model: gemini-embedding-001 + apiKey: some-key + dimension: 768`, + want: `kind: sources +name: my-pg-instance +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +database: my_db +user: my_user +password: my_pass +--- +kind: authServices +name: my-google-auth +type: google +clientId: testing-id +--- +kind: tools +name: example_tool +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: toolsets +name: example_toolset +tools: +- example_tool +--- +kind: prompts +name: code_review +description: ask llm to analyze code quality +messages: +- content: "please review the following code for quality: {{.code}}" +arguments: +- name: code + description: the code to review +--- +kind: embeddingModels +name: gemini-model +type: gemini +model: gemini-embedding-001 +apiKey: some-key +dimension: 768 +`, + }, + { + desc: "preserve resource order", + in: ` + tools: + example_tool: + kind: postgres-sql + source: my-pg-instance + description: some description + statement: SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + sources: + my-pg-instance: + kind: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + authServices: + my-google-auth: + kind: google + clientId: testing-id + toolsets: + example_toolset: + - example_tool + authSources: + my-google-auth2: + kind: google + clientId: testing-id`, + want: `kind: tools +name: example_tool +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: sources +name: my-pg-instance +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +database: my_db +user: my_user +password: my_pass +--- +kind: authServices +name: my-google-auth +type: google +clientId: testing-id +--- +kind: toolsets +name: example_toolset +tools: +- example_tool +--- +kind: authServices +name: my-google-auth2 +type: google +clientId: testing-id +`, + }, + { + desc: "convert combination of v1 and v2", + in: ` + sources: + my-pg-instance: + kind: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + authServices: + my-google-auth: + kind: google + clientId: testing-id + tools: + example_tool: + kind: postgres-sql + source: my-pg-instance + description: some description + statement: SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + toolsets: + example_toolset: + - example_tool + prompts: + code_review: + description: ask llm to analyze code quality + messages: + - content: "please review the following code for quality: {{.code}}" + arguments: + - name: code + description: the code to review + embeddingModels: + gemini-model: + kind: gemini + model: gemini-embedding-001 + apiKey: some-key + dimension: 768 +--- + kind: sources + name: my-pg-instance2 + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance +--- + kind: authServices + name: my-google-auth2 + type: google + clientId: testing-id +--- + kind: tools + name: example_tool2 + type: postgres-sql + source: my-pg-instance + description: some description + statement: SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description +--- + kind: toolsets + name: example_toolset2 + tools: + - example_tool +--- + tools: + - example_tool + kind: toolsets + name: example_toolset3 +--- + kind: prompts + name: code_review2 + description: ask llm to analyze code quality + messages: + - content: "please review the following code for quality: {{.code}}" + arguments: + - name: code + description: the code to review +--- + kind: embeddingModels + name: gemini-model2 + type: gemini`, + want: `kind: sources +name: my-pg-instance +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +database: my_db +user: my_user +password: my_pass +--- +kind: authServices +name: my-google-auth +type: google +clientId: testing-id +--- +kind: tools +name: example_tool +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: toolsets +name: example_toolset +tools: +- example_tool +--- +kind: prompts +name: code_review +description: ask llm to analyze code quality +messages: +- content: "please review the following code for quality: {{.code}}" +arguments: +- name: code + description: the code to review +--- +kind: embeddingModels +name: gemini-model +type: gemini +model: gemini-embedding-001 +apiKey: some-key +dimension: 768 +--- +kind: sources +name: my-pg-instance2 +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +--- +kind: authServices +name: my-google-auth2 +type: google +clientId: testing-id +--- +kind: tools +name: example_tool2 +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: toolsets +name: example_toolset2 +tools: +- example_tool +--- +tools: +- example_tool +kind: toolsets +name: example_toolset3 +--- +kind: prompts +name: code_review2 +description: ask llm to analyze code quality +messages: +- content: "please review the following code for quality: {{.code}}" +arguments: +- name: code + description: the code to review +--- +kind: embeddingModels +name: gemini-model2 +type: gemini +`, + }, + { + desc: "no convertion needed", + in: `kind: sources +name: my-pg-instance +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +database: my_db +user: my_user +password: my_pass +--- +kind: tools +name: example_tool +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: toolsets +name: example_toolset +tools: +- example_tool`, + want: `kind: sources +name: my-pg-instance +type: cloud-sql-postgres +project: my-project +region: my-region +instance: my-instance +database: my_db +user: my_user +password: my_pass +--- +kind: tools +name: example_tool +type: postgres-sql +source: my-pg-instance +description: some description +statement: SELECT * FROM SQL_STATEMENT; +parameters: +- name: country + type: string + description: some description +--- +kind: toolsets +name: example_toolset +tools: +- example_tool +`, + }, + { + desc: "invalid source", + in: `sources: invalid`, + want: "", + }, + { + desc: "invalid toolset", + in: `toolsets: invalid`, + want: "", + }, + } + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + output, err := convertToolsFile([]byte(tc.in)) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if diff := cmp.Diff(string(output), tc.want); diff != "" { + t.Fatalf("incorrect toolsets parse: diff %v", diff) + } + }) + } +} + func TestParseToolFile(t *testing.T) { ctx, err := testutils.ContextWithNewLogger() if err != nil { @@ -525,7 +956,7 @@ func TestParseToolFile(t *testing.T) { wantToolsFile ToolsFile }{ { - description: "basic example", + description: "basic example tools file v1", in: ` sources: my-pg-instance: @@ -555,7 +986,7 @@ func TestParseToolFile(t *testing.T) { Sources: server.SourceConfigs{ "my-pg-instance": cloudsqlpgsrc.Config{ Name: "my-pg-instance", - Kind: cloudsqlpgsrc.SourceKind, + Type: cloudsqlpgsrc.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -568,7 +999,7 @@ func TestParseToolFile(t *testing.T) { Tools: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -584,20 +1015,135 @@ func TestParseToolFile(t *testing.T) { ToolNames: []string{"example_tool"}, }, }, - Prompts: nil, + AuthServices: nil, + Prompts: nil, }, }, { - description: "with prompts example", + description: "basic example tools file v2", in: ` - prompts: - my-prompt: - description: A prompt template for data analysis. - arguments: - - name: country - description: The country to analyze. - messages: - - content: Analyze the data for {{.country}}. + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass +--- + kind: authServices + name: my-google-auth + type: google + clientId: testing-id +--- + kind: embeddingModels + name: gemini-model + type: gemini + model: gemini-embedding-001 + apiKey: some-key + dimension: 768 +--- + kind: tools + name: example_tool + type: postgres-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description +--- + kind: toolsets + name: example_toolset + tools: + - example_tool +--- + kind: prompts + name: code_review + description: ask llm to analyze code quality + messages: + - content: "please review the following code for quality: {{.code}}" + arguments: + - name: code + description: the code to review + `, + wantToolsFile: ToolsFile{ + Sources: server.SourceConfigs{ + "my-pg-instance": cloudsqlpgsrc.Config{ + Name: "my-pg-instance", + Type: cloudsqlpgsrc.SourceType, + Project: "my-project", + Region: "my-region", + Instance: "my-instance", + IPType: "public", + Database: "my_db", + User: "my_user", + Password: "my_pass", + }, + }, + AuthServices: server.AuthServiceConfigs{ + "my-google-auth": google.Config{ + Name: "my-google-auth", + Type: google.AuthServiceType, + ClientID: "testing-id", + }, + }, + EmbeddingModels: server.EmbeddingModelConfigs{ + "gemini-model": gemini.Config{ + Name: "gemini-model", + Type: gemini.EmbeddingModelType, + Model: "gemini-embedding-001", + ApiKey: "some-key", + Dimension: 768, + }, + }, + Tools: server.ToolConfigs{ + "example_tool": postgressql.Config{ + Name: "example_tool", + Type: "postgres-sql", + Source: "my-pg-instance", + Description: "some description", + Statement: "SELECT * FROM SQL_STATEMENT;\n", + Parameters: []parameters.Parameter{ + parameters.NewStringParameter("country", "some description"), + }, + AuthRequired: []string{}, + }, + }, + Toolsets: server.ToolsetConfigs{ + "example_toolset": tools.ToolsetConfig{ + Name: "example_toolset", + ToolNames: []string{"example_tool"}, + }, + }, + Prompts: server.PromptConfigs{ + "code_review": &custom.Config{ + Name: "code_review", + Description: "ask llm to analyze code quality", + Arguments: prompts.Arguments{ + {Parameter: parameters.NewStringParameter("code", "the code to review")}, + }, + Messages: []prompts.Message{ + {Role: "user", Content: "please review the following code for quality: {{.code}}"}, + }, + }, + }, + }, + }, + { + description: "only prompts", + in: ` + kind: prompts + name: my-prompt + description: A prompt template for data analysis. + arguments: + - name: country + description: The country to analyze. + messages: + - content: Analyze the data for {{.country}}. `, wantToolsFile: ToolsFile{ Sources: nil, @@ -658,58 +1204,62 @@ func TestParseToolFileWithAuth(t *testing.T) { { description: "basic example", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - authServices: - my-google-service: - kind: google - clientId: my-client-id - other-google-service: - kind: google - clientId: other-client-id - - tools: - example_tool: - kind: postgres-sql - source: my-pg-instance + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass +--- + kind: authServices + name: my-google-service + type: google + clientId: my-client-id +--- + kind: authServices + name: other-google-service + type: google + clientId: other-client-id +--- + kind: tools + name: example_tool + type: postgres-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description - - name: id - type: integer - description: user id - authServices: - - name: my-google-service - field: user_id - - name: email - type: string - description: user email - authServices: - - name: my-google-service - field: email - - name: other-google-service - field: other_email - - toolsets: - example_toolset: - - example_tool + - name: id + type: integer + description: user id + authServices: + - name: my-google-service + field: user_id + - name: email + type: string + description: user email + authServices: + - name: my-google-service + field: email + - name: other-google-service + field: other_email +--- + kind: toolsets + name: example_toolset + tools: + - example_tool `, wantToolsFile: ToolsFile{ Sources: server.SourceConfigs{ "my-pg-instance": cloudsqlpgsrc.Config{ Name: "my-pg-instance", - Kind: cloudsqlpgsrc.SourceKind, + Type: cloudsqlpgsrc.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -722,19 +1272,19 @@ func TestParseToolFileWithAuth(t *testing.T) { AuthServices: server.AuthServiceConfigs{ "my-google-service": google.Config{ Name: "my-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "my-client-id", }, "other-google-service": google.Config{ Name: "other-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "other-client-id", }, }, Tools: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -809,7 +1359,7 @@ func TestParseToolFileWithAuth(t *testing.T) { Sources: server.SourceConfigs{ "my-pg-instance": cloudsqlpgsrc.Config{ Name: "my-pg-instance", - Kind: cloudsqlpgsrc.SourceKind, + Type: cloudsqlpgsrc.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -819,22 +1369,22 @@ func TestParseToolFileWithAuth(t *testing.T) { Password: "my_pass", }, }, - AuthSources: server.AuthServiceConfigs{ + AuthServices: server.AuthServiceConfigs{ "my-google-service": google.Config{ Name: "my-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "my-client-id", }, "other-google-service": google.Config{ Name: "other-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "other-client-id", }, }, Tools: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -858,60 +1408,64 @@ func TestParseToolFileWithAuth(t *testing.T) { { description: "basic example with authRequired", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - authServices: - my-google-service: - kind: google - clientId: my-client-id - other-google-service: - kind: google - clientId: other-client-id - - tools: - example_tool: - kind: postgres-sql - source: my-pg-instance + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass +--- + kind: authServices + name: my-google-service + type: google + clientId: my-client-id +--- + kind: authServices + name: other-google-service + type: google + clientId: other-client-id +--- + kind: tools + name: example_tool + type: postgres-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-service + parameters: + - name: country + type: string description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-service - parameters: - - name: country - type: string - description: some description - - name: id - type: integer - description: user id - authServices: - - name: my-google-service - field: user_id - - name: email - type: string - description: user email - authServices: - - name: my-google-service - field: email - - name: other-google-service - field: other_email - - toolsets: - example_toolset: - - example_tool + - name: id + type: integer + description: user id + authServices: + - name: my-google-service + field: user_id + - name: email + type: string + description: user email + authServices: + - name: my-google-service + field: email + - name: other-google-service + field: other_email +--- + kind: toolsets + name: example_toolset + tools: + - example_tool `, wantToolsFile: ToolsFile{ Sources: server.SourceConfigs{ "my-pg-instance": cloudsqlpgsrc.Config{ Name: "my-pg-instance", - Kind: cloudsqlpgsrc.SourceKind, + Type: cloudsqlpgsrc.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -924,19 +1478,19 @@ func TestParseToolFileWithAuth(t *testing.T) { AuthServices: server.AuthServiceConfigs{ "my-google-service": google.Config{ Name: "my-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "my-client-id", }, "other-google-service": google.Config{ Name: "other-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "other-client-id", }, }, Tools: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -1082,7 +1636,7 @@ func TestEnvVarReplacement(t *testing.T) { Sources: server.SourceConfigs{ "my-http-instance": httpsrc.Config{ Name: "my-http-instance", - Kind: httpsrc.SourceKind, + Type: httpsrc.SourceType, BaseURL: "http://test_server/", Timeout: "10s", DefaultHeaders: map[string]string{"Authorization": "ACTUAL_HEADER"}, @@ -1092,19 +1646,165 @@ func TestEnvVarReplacement(t *testing.T) { AuthServices: server.AuthServiceConfigs{ "my-google-service": google.Config{ Name: "my-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "ACTUAL_CLIENT_ID", }, "other-google-service": google.Config{ Name: "other-google-service", - Kind: google.AuthServiceKind, + Type: google.AuthServiceType, ClientID: "ACTUAL_CLIENT_ID_2", }, }, Tools: server.ToolConfigs{ "example_tool": http.Config{ Name: "example_tool", - Kind: "http", + Type: "http", + Source: "my-instance", + Method: "GET", + Path: "search?name=alice&pet=cat", + Description: "some description", + AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, + QueryParams: []parameters.Parameter{ + parameters.NewStringParameterWithAuth("country", "some description", + []parameters.ParamAuthService{{Name: "my-google-auth-service", Field: "user_id"}, + {Name: "other-auth-service", Field: "user_id"}}), + }, + RequestBody: `{ + "age": {{.age}}, + "city": "{{.city}}", + "food": "food", + "other": "$OTHER" +} +`, + BodyParams: []parameters.Parameter{parameters.NewIntParameter("age", "age num"), parameters.NewStringParameter("city", "city string")}, + Headers: map[string]string{"Authorization": "API_KEY", "Content-Type": "application/json"}, + HeaderParams: []parameters.Parameter{parameters.NewStringParameter("Language", "language string")}, + }, + }, + Toolsets: server.ToolsetConfigs{ + "ACTUAL_TOOLSET_NAME": tools.ToolsetConfig{ + Name: "ACTUAL_TOOLSET_NAME", + ToolNames: []string{"example_tool"}, + }, + }, + Prompts: server.PromptConfigs{ + "ACTUAL_PROMPT_NAME": &custom.Config{ + Name: "ACTUAL_PROMPT_NAME", + Description: "A test prompt for {{.name}}.", + Messages: []prompts.Message{ + { + Role: "user", + Content: "ACTUAL_CONTENT", + }, + }, + Arguments: nil, + }, + }, + }, + }, + { + description: "file with env var example toolsfile v2", + in: ` + kind: sources + name: my-http-instance + type: http + baseUrl: http://test_server/ + timeout: 10s + headers: + Authorization: ${TestHeader} + queryParams: + api-key: ${API_KEY} +--- + kind: authServices + name: my-google-service + type: google + clientId: ${clientId} +--- + kind: authServices + name: other-google-service + type: google + clientId: ${clientId2} +--- + kind: tools + name: example_tool + type: http + source: my-instance + method: GET + path: "search?name=alice&pet=${cat_string}" + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + queryParams: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + requestBody: | + { + "age": {{.age}}, + "city": "{{.city}}", + "food": "${food_string}", + "other": "$OTHER" + } + bodyParams: + - name: age + type: integer + description: age num + - name: city + type: string + description: city string + headers: + Authorization: API_KEY + Content-Type: application/json + headerParams: + - name: Language + type: string + description: language string +--- + kind: toolsets + name: ${toolset_name} + tools: + - example_tool +--- + kind: prompts + name: ${prompt_name} + description: A test prompt for {{.name}}. + messages: + - role: user + content: ${prompt_content} + `, + wantToolsFile: ToolsFile{ + Sources: server.SourceConfigs{ + "my-http-instance": httpsrc.Config{ + Name: "my-http-instance", + Type: httpsrc.SourceType, + BaseURL: "http://test_server/", + Timeout: "10s", + DefaultHeaders: map[string]string{"Authorization": "ACTUAL_HEADER"}, + QueryParams: map[string]string{"api-key": "ACTUAL_API_KEY"}, + }, + }, + AuthServices: server.AuthServiceConfigs{ + "my-google-service": google.Config{ + Name: "my-google-service", + Type: google.AuthServiceType, + ClientID: "ACTUAL_CLIENT_ID", + }, + "other-google-service": google.Config{ + Name: "other-google-service", + Type: google.AuthServiceType, + ClientID: "ACTUAL_CLIENT_ID_2", + }, + }, + Tools: server.ToolConfigs{ + "example_tool": http.Config{ + Name: "example_tool", + Type: "http", Source: "my-instance", Method: "GET", Path: "search?name=alice&pet=cat", @@ -1970,17 +2670,18 @@ func TestPrebuiltAndCustomTools(t *testing.T) { t.Setenv("SQLITE_DATABASE", "test.db") // Setup custom tools file customContent := ` -tools: - custom_tool: - kind: http - source: my-http - method: GET - path: / - description: "A custom tool for testing" -sources: - my-http: - kind: http - baseUrl: http://example.com +kind: tools +name: custom_tool +type: http +source: my-http +method: GET +path: / +description: "A custom tool for testing" +--- +kind: sources +name: my-http +type: http +baseUrl: http://example.com ` customFile := filepath.Join(t.TempDir(), "custom.yaml") if err := os.WriteFile(customFile, []byte(customContent), 0644); err != nil { @@ -1990,17 +2691,18 @@ sources: // Tool Conflict File // SQLite prebuilt has a tool named 'list_tables' toolConflictContent := ` -tools: - list_tables: - kind: http - source: my-http - method: GET - path: / - description: "Conflicting tool" -sources: - my-http: - kind: http - baseUrl: http://example.com +kind: tools +name: list_tables +type: http +source: my-http +method: GET +path: / +description: "Conflicting tool" +--- +kind: sources +name: my-http +type: http +baseUrl: http://example.com ` toolConflictFile := filepath.Join(t.TempDir(), "tool_conflict.yaml") if err := os.WriteFile(toolConflictFile, []byte(toolConflictContent), 0644); err != nil { @@ -2010,17 +2712,18 @@ sources: // Source Conflict File // SQLite prebuilt has a source named 'sqlite-source' sourceConflictContent := ` -sources: - sqlite-source: - kind: http - baseUrl: http://example.com -tools: - dummy_tool: - kind: http - source: sqlite-source - method: GET - path: / - description: "Dummy" +kind: sources +name: sqlite-source +type: http +baseUrl: http://example.com +--- +kind: tools +name: dummy_tool +type: http +source: sqlite-source +method: GET +path: / +description: "Dummy" ` sourceConflictFile := filepath.Join(t.TempDir(), "source_conflict.yaml") if err := os.WriteFile(sourceConflictFile, []byte(sourceConflictContent), 0644); err != nil { @@ -2030,20 +2733,23 @@ tools: // Toolset Conflict File // SQLite prebuilt has a toolset named 'sqlite_database_tools' toolsetConflictContent := ` -sources: - dummy-src: - kind: http - baseUrl: http://example.com +kind: sources +name: dummy-src +type: http +baseUrl: http://example.com +--- +kind: tools +name: dummy_tool +type: http +source: dummy-src +method: GET +path: / +description: "Dummy" +--- +kind: toolsets +name: sqlite_database_tools tools: - dummy_tool: - kind: http - source: dummy-src - method: GET - path: / - description: "Dummy" -toolsets: - sqlite_database_tools: - - dummy_tool +- dummy_tool ` toolsetConflictFile := filepath.Join(t.TempDir(), "toolset_conflict.yaml") if err := os.WriteFile(toolsetConflictFile, []byte(toolsetConflictContent), 0644); err != nil { diff --git a/docs/en/about/faq.md b/docs/en/about/faq.md index 683c49c6b06b..5ab557e0995a 100644 --- a/docs/en/about/faq.md +++ b/docs/en/about/faq.md @@ -45,7 +45,7 @@ most popular issues, so make sure to +1 ones you are the most interested in. ## Can Toolbox be used for non-database tools? **Yes!** While Toolbox is primarily focused on databases, it also supports generic -**HTTP tools** (`kind: http`). These allow you to connect your agents to REST APIs +**HTTP tools** (`type: http`). These allow you to connect your agents to REST APIs and other web services, enabling workflows that extend beyond database interactions. For configuration details, see the [HTTP Tools documentation](../resources/tools/http/http.md). diff --git a/docs/en/concepts/telemetry/index.md b/docs/en/concepts/telemetry/index.md index 49b7c9edca5d..9bd159805235 100644 --- a/docs/en/concepts/telemetry/index.md +++ b/docs/en/concepts/telemetry/index.md @@ -64,7 +64,7 @@ The structured logging outputs log as JSON: "timestamp":"2024-11-04T16:45:11.987299-08:00", "severity":"ERROR", "logging.googleapis.com/sourceLocation":{...}, - "message":"unable to parse tool file at \"tools.yaml\": \"cloud-sql-postgres1\" is not a valid kind of data source" + "message":"unable to parse tool file at \"tools.yaml\": \"cloud-sql-postgres1\" is not a valid type of data source" } ``` diff --git a/docs/en/getting-started/colab_quickstart.ipynb b/docs/en/getting-started/colab_quickstart.ipynb index 4260b60bb3a8..328115814763 100644 --- a/docs/en/getting-started/colab_quickstart.ipynb +++ b/docs/en/getting-started/colab_quickstart.ipynb @@ -300,78 +300,89 @@ "# You can also upload a tools file and use that to run toolbox.\n", "tools_file_name = \"tools.yml\"\n", "file_content = f\"\"\"\n", - "sources:\n", - " my-pg-source:\n", - " kind: postgres\n", - " host: 127.0.0.1\n", - " port: 5432\n", - " database: toolbox_db\n", - " user: toolbox_user\n", - " password: my-password\n", + "kind: sources\n", + "name: my-pg-source\n", + "type: postgres\n", + "host: 127.0.0.1\n", + "port: 5432\n", + "database: toolbox_db\n", + "user: toolbox_user\n", + "password: my-password\n", + "---\n", + "kind: tools\n", + "name: search-hotels-by-name\n", + "type: postgres-sql\n", + "source: my-pg-source\n", + "description: Search for hotels based on name.\n", + "parameters:\n", + " - name: name\n", + " type: string\n", + " description: The name of the hotel.\n", + "statement: SELECT * FROM hotels WHERE name ILIKE '%' || \\$1 || '%';\n", + "---\n", + "kind: tools\n", + "name: search-hotels-by-location\n", + "type: postgres-sql\n", + "source: my-pg-source\n", + "description: Search for hotels based on location.\n", + "parameters:\n", + " - name: location\n", + " type: string\n", + " description: The location of the hotel.\n", + "statement: SELECT * FROM hotels WHERE location ILIKE '%' || \\$1 || '%';\n", + "---\n", + "kind: tools\n", + "name: book-hotel\n", + "type: postgres-sql\n", + "source: my-pg-source\n", + "description: >-\n", + " Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not.\n", + "parameters:\n", + " - name: hotel_id\n", + " type: string\n", + " description: The ID of the hotel to book.\n", + "statement: UPDATE hotels SET booked = B'1' WHERE id = \\$1;\n", + "---\n", + "kind: tools\n", + "name: update-hotel\n", + "type: postgres-sql\n", + "source: my-pg-source\n", + "description: >-\n", + " Update a hotel's check-in and check-out dates by its ID. Returns a message\n", + " indicating whether the hotel was successfully updated or not.\n", + "parameters:\n", + " - name: hotel_id\n", + " type: string\n", + " description: The ID of the hotel to update.\n", + " - name: checkin_date\n", + " type: string\n", + " description: The new check-in date of the hotel.\n", + " - name: checkout_date\n", + " type: string\n", + " description: The new check-out date of the hotel.\n", + "statement: >-\n", + " UPDATE hotels SET checkin_date = CAST(\\$2 as date), checkout_date = CAST(\\$3\n", + " as date) WHERE id = \\$1;\n", + "---\n", + "kind: tools\n", + "name: cancel-hotel\n", + "type: postgres-sql\n", + "source: my-pg-source\n", + "description: Cancel a hotel by its ID.\n", + "parameters:\n", + " - name: hotel_id\n", + " type: string\n", + " description: The ID of the hotel to cancel.\n", + "statement: UPDATE hotels SET booked = B'0' WHERE id = \\$1;\n", + "---\n", + "kind: toolsets\n", + "name: my-toolset\n", "tools:\n", - " search-hotels-by-name:\n", - " kind: postgres-sql\n", - " source: my-pg-source\n", - " description: Search for hotels based on name.\n", - " parameters:\n", - " - name: name\n", - " type: string\n", - " description: The name of the hotel.\n", - " statement: SELECT * FROM hotels WHERE name ILIKE '%' || \\$1 || '%';\n", - " search-hotels-by-location:\n", - " kind: postgres-sql\n", - " source: my-pg-source\n", - " description: Search for hotels based on location.\n", - " parameters:\n", - " - name: location\n", - " type: string\n", - " description: The location of the hotel.\n", - " statement: SELECT * FROM hotels WHERE location ILIKE '%' || \\$1 || '%';\n", - " book-hotel:\n", - " kind: postgres-sql\n", - " source: my-pg-source\n", - " description: >-\n", - " Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not.\n", - " parameters:\n", - " - name: hotel_id\n", - " type: string\n", - " description: The ID of the hotel to book.\n", - " statement: UPDATE hotels SET booked = B'1' WHERE id = \\$1;\n", - " update-hotel:\n", - " kind: postgres-sql\n", - " source: my-pg-source\n", - " description: >-\n", - " Update a hotel's check-in and check-out dates by its ID. Returns a message\n", - " indicating whether the hotel was successfully updated or not.\n", - " parameters:\n", - " - name: hotel_id\n", - " type: string\n", - " description: The ID of the hotel to update.\n", - " - name: checkin_date\n", - " type: string\n", - " description: The new check-in date of the hotel.\n", - " - name: checkout_date\n", - " type: string\n", - " description: The new check-out date of the hotel.\n", - " statement: >-\n", - " UPDATE hotels SET checkin_date = CAST(\\$2 as date), checkout_date = CAST(\\$3\n", - " as date) WHERE id = \\$1;\n", - " cancel-hotel:\n", - " kind: postgres-sql\n", - " source: my-pg-source\n", - " description: Cancel a hotel by its ID.\n", - " parameters:\n", - " - name: hotel_id\n", - " type: string\n", - " description: The ID of the hotel to cancel.\n", - " statement: UPDATE hotels SET booked = B'0' WHERE id = \\$1;\n", - "toolsets:\n", - " my-toolset:\n", - " - search-hotels-by-name\n", - " - search-hotels-by-location\n", - " - book-hotel\n", - " - update-hotel\n", - " - cancel-hotel\n", + " - search-hotels-by-name\n", + " - search-hotels-by-location\n", + " - book-hotel\n", + " - update-hotel\n", + " - cancel-hotel\n", "\"\"\"" ] }, diff --git a/docs/en/getting-started/configure.md b/docs/en/getting-started/configure.md index 6155eb56083d..e578c64dfc63 100644 --- a/docs/en/getting-started/configure.md +++ b/docs/en/getting-started/configure.md @@ -36,14 +36,14 @@ Toolbox should have access to. Most tools will have at least one source to execute against. ```yaml -sources: - my-pg-source: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: toolbox_db - user: ${USER_NAME} - password: ${PASSWORD} +kind: sources +name: my-pg-source +type: postgres +host: 127.0.0.1 +port: 5432 +database: toolbox_db +user: ${USER_NAME} +password: ${PASSWORD} ``` For more details on configuring different types of sources, see the @@ -52,20 +52,20 @@ For more details on configuring different types of sources, see the ### Tools The `tools` section of your `tools.yaml` defines the actions your agent can -take: what kind of tool it is, which source(s) it affects, what parameters it +take: what type of tool it is, which source(s) it affects, what parameters it uses, etc. ```yaml -tools: - search-hotels-by-name: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; +kind: tools +name: search-hotels-by-name +type: postgres-sql +source: my-pg-source +description: Search for hotels based on name. +parameters: + - name: name + type: string + description: The name of the hotel. +statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; ``` For more details on configuring different types of tools, see the @@ -78,13 +78,17 @@ that you want to be able to load together. This can be useful for defining different sets for different agents or different applications. ```yaml -toolsets: - my_first_toolset: - - my_first_tool - - my_second_tool - my_second_toolset: - - my_second_tool - - my_third_tool +kind: toolsets +name: my_first_toolset +tools: + - my_first_tool + - my_second_tool +--- +kind: toolsets +name: my_second_toolset +tools: + - my_second_tool + - my_third_tool ``` You can load toolsets by name: @@ -103,14 +107,14 @@ The `prompts` section of your `tools.yaml` defines the templates containing structured messages and instructions for interacting with language models. ```yaml -prompts: - code_review: - description: "Asks the LLM to analyze code quality and suggest improvements." - messages: - - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" - arguments: - - name: "code" - description: "The code to review" +kind: prompts +name: code_review +description: "Asks the LLM to analyze code quality and suggest improvements." +messages: + - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" +arguments: + - name: "code" + description: "The code to review" ``` For more details on configuring different types of prompts, see the diff --git a/docs/en/getting-started/introduction/_index.md b/docs/en/getting-started/introduction/_index.md index 5fb0b757c8fc..0a3e2bff4dd1 100644 --- a/docs/en/getting-started/introduction/_index.md +++ b/docs/en/getting-started/introduction/_index.md @@ -16,6 +16,12 @@ Databases” as its initial development predated MCP, but was renamed to align with recently added MCP compatibility. {{< /notice >}} +{{< notice note >}} +This document has been updated to support the configuration file v2 format. To +view documentation with configuration file v1 format, please navigate to the +top-right menu and select versions v0.26.0 or older. +{{< /notice >}} + ## Why Toolbox? Toolbox helps you build Gen AI tools that let your agents access data in your diff --git a/docs/en/getting-started/mcp_quickstart/_index.md b/docs/en/getting-started/mcp_quickstart/_index.md index 7967d574a550..0bc7b94733a9 100644 --- a/docs/en/getting-started/mcp_quickstart/_index.md +++ b/docs/en/getting-started/mcp_quickstart/_index.md @@ -125,78 +125,89 @@ In this section, we will download Toolbox, configure our tools in a {{< /notice >}} ```yaml - sources: - my-pg-source: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: toolbox_db - user: toolbox_user - password: my-password + kind: sources + name: my-pg-source + type: postgres + host: 127.0.0.1 + port: 5432 + database: toolbox_db + user: toolbox_user + password: my-password + --- + kind: tools + name: search-hotels-by-name + type: postgres-sql + source: my-pg-source + description: Search for hotels based on name. + parameters: + - name: name + type: string + description: The name of the hotel. + statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; + --- + kind: tools + name: search-hotels-by-location + type: postgres-sql + source: my-pg-source + description: Search for hotels based on location. + parameters: + - name: location + type: string + description: The location of the hotel. + statement: SELECT * FROM hotels WHERE location ILIKE '%' || $1 || '%'; + --- + kind: tools + name: book-hotel + type: postgres-sql + source: my-pg-source + description: >- + Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to book. + statement: UPDATE hotels SET booked = B'1' WHERE id = $1; + --- + kind: tools + name: update-hotel + type: postgres-sql + source: my-pg-source + description: >- + Update a hotel's check-in and check-out dates by its ID. Returns a message + indicating whether the hotel was successfully updated or not. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to update. + - name: checkin_date + type: string + description: The new check-in date of the hotel. + - name: checkout_date + type: string + description: The new check-out date of the hotel. + statement: >- + UPDATE hotels SET checkin_date = CAST($2 as date), checkout_date = CAST($3 + as date) WHERE id = $1; + --- + kind: tools + name: cancel-hotel + type: postgres-sql + source: my-pg-source + description: Cancel a hotel by its ID. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to cancel. + statement: UPDATE hotels SET booked = B'0' WHERE id = $1; + --- + kind: toolsets + name: my-toolset tools: - search-hotels-by-name: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; - search-hotels-by-location: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on location. - parameters: - - name: location - type: string - description: The location of the hotel. - statement: SELECT * FROM hotels WHERE location ILIKE '%' || $1 || '%'; - book-hotel: - kind: postgres-sql - source: my-pg-source - description: >- - Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to book. - statement: UPDATE hotels SET booked = B'1' WHERE id = $1; - update-hotel: - kind: postgres-sql - source: my-pg-source - description: >- - Update a hotel's check-in and check-out dates by its ID. Returns a message - indicating whether the hotel was successfully updated or not. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to update. - - name: checkin_date - type: string - description: The new check-in date of the hotel. - - name: checkout_date - type: string - description: The new check-out date of the hotel. - statement: >- - UPDATE hotels SET checkin_date = CAST($2 as date), checkout_date = CAST($3 - as date) WHERE id = $1; - cancel-hotel: - kind: postgres-sql - source: my-pg-source - description: Cancel a hotel by its ID. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to cancel. - statement: UPDATE hotels SET booked = B'0' WHERE id = $1; - toolsets: - my-toolset: - - search-hotels-by-name - - search-hotels-by-location - - book-hotel - - update-hotel - - cancel-hotel + - search-hotels-by-name + - search-hotels-by-location + - book-hotel + - update-hotel + - cancel-hotel ``` For more info on tools, check out the diff --git a/docs/en/getting-started/prompts_quickstart_gemini_cli.md b/docs/en/getting-started/prompts_quickstart_gemini_cli.md index 2061acd7fae9..47140ed2e726 100644 --- a/docs/en/getting-started/prompts_quickstart_gemini_cli.md +++ b/docs/en/getting-started/prompts_quickstart_gemini_cli.md @@ -157,61 +157,67 @@ Create a file named `tools.yaml`. This file defines the database connection, the SQL tools available, and the prompts the agents will use. ```yaml -sources: - my-foodiefind-db: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: toolbox_db - user: toolbox_user - password: my-password -tools: - find_user_by_email: - kind: postgres-sql - source: my-foodiefind-db - description: Find a user's ID by their email address. - parameters: - - name: email - type: string - description: The email address of the user to find. - statement: SELECT id FROM users WHERE email = $1; - find_restaurant_by_name: - kind: postgres-sql - source: my-foodiefind-db - description: Find a restaurant's ID by its exact name. - parameters: - - name: name - type: string - description: The name of the restaurant to find. - statement: SELECT id FROM restaurants WHERE name = $1; - find_review_by_user_and_restaurant: - kind: postgres-sql - source: my-foodiefind-db - description: Find the full record for a specific review using the user's ID and the restaurant's ID. - parameters: - - name: user_id - type: integer - description: The numerical ID of the user. - - name: restaurant_id - type: integer - description: The numerical ID of the restaurant. - statement: SELECT * FROM reviews WHERE user_id = $1 AND restaurant_id = $2; -prompts: - investigate_missing_review: - description: "Investigates a user's missing review by finding the user, restaurant, and the review itself, then analyzing its status." - arguments: - - name: "user_email" - description: "The email of the user who wrote the review." - - name: "restaurant_name" - description: "The name of the restaurant being reviewed." - messages: - - content: >- - **Goal:** Find the review written by the user with email '{{.user_email}}' for the restaurant named '{{.restaurant_name}}' and understand its status. - **Workflow:** - 1. Use the `find_user_by_email` tool with the email '{{.user_email}}' to get the `user_id`. - 2. Use the `find_restaurant_by_name` tool with the name '{{.restaurant_name}}' to get the `restaurant_id`. - 3. Use the `find_review_by_user_and_restaurant` tool with the `user_id` and `restaurant_id` you just found. - 4. Analyze the results from the final tool call. Examine the `is_published` and `moderation_status` fields and explain the review's status to the user in a clear, human-readable sentence. +kind: sources +name: my-foodiefind-db +type: postgres +host: 127.0.0.1 +port: 5432 +database: toolbox_db +user: toolbox_user +password: my-password +--- +kind: tools +name: find_user_by_email +type: postgres-sql +source: my-foodiefind-db +description: Find a user's ID by their email address. +parameters: + - name: email + type: string + description: The email address of the user to find. +statement: SELECT id FROM users WHERE email = $1; +--- +kind: tools +name: find_restaurant_by_name +type: postgres-sql +source: my-foodiefind-db +description: Find a restaurant's ID by its exact name. +parameters: + - name: name + type: string + description: The name of the restaurant to find. +statement: SELECT id FROM restaurants WHERE name = $1; +--- +kind: tools +name: find_review_by_user_and_restaurant +type: postgres-sql +source: my-foodiefind-db +description: Find the full record for a specific review using the user's ID and the restaurant's ID. +parameters: + - name: user_id + type: integer + description: The numerical ID of the user. + - name: restaurant_id + type: integer + description: The numerical ID of the restaurant. +statement: SELECT * FROM reviews WHERE user_id = $1 AND restaurant_id = $2; +--- +kind: prompts +name: investigate_missing_review +description: "Investigates a user's missing review by finding the user, restaurant, and the review itself, then analyzing its status." +arguments: + - name: "user_email" + description: "The email of the user who wrote the review." + - name: "restaurant_name" + description: "The name of the restaurant being reviewed." +messages: + - content: >- + **Goal:** Find the review written by the user with email '{{.user_email}}' for the restaurant named '{{.restaurant_name}}' and understand its status. + **Workflow:** + 1. Use the `find_user_by_email` tool with the email '{{.user_email}}' to get the `user_id`. + 2. Use the `find_restaurant_by_name` tool with the name '{{.restaurant_name}}' to get the `restaurant_id`. + 3. Use the `find_review_by_user_and_restaurant` tool with the `user_id` and `restaurant_id` you just found. + 4. Analyze the results from the final tool call. Examine the `is_published` and `moderation_status` fields and explain the review's status to the user in a clear, human-readable sentence. ``` ## Step 3: Connect to Gemini CLI diff --git a/docs/en/getting-started/quickstart/shared/configure_toolbox.md b/docs/en/getting-started/quickstart/shared/configure_toolbox.md index 12436ee7d613..bea2ed4d60f4 100644 --- a/docs/en/getting-started/quickstart/shared/configure_toolbox.md +++ b/docs/en/getting-started/quickstart/shared/configure_toolbox.md @@ -33,78 +33,89 @@ In this section, we will download Toolbox, configure our tools in a {{< /notice >}} ```yaml - sources: - my-pg-source: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: toolbox_db - user: ${USER_NAME} - password: ${PASSWORD} + kind: sources + name: my-pg-source + type: postgres + host: 127.0.0.1 + port: 5432 + database: toolbox_db + user: toolbox_user + password: my-password + --- + kind: tools + name: search-hotels-by-name + type: postgres-sql + source: my-pg-source + description: Search for hotels based on name. + parameters: + - name: name + type: string + description: The name of the hotel. + statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; + --- + kind: tools + name: search-hotels-by-location + type: postgres-sql + source: my-pg-source + description: Search for hotels based on location. + parameters: + - name: location + type: string + description: The location of the hotel. + statement: SELECT * FROM hotels WHERE location ILIKE '%' || $1 || '%'; + --- + kind: tools + name: book-hotel + type: postgres-sql + source: my-pg-source + description: >- + Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to book. + statement: UPDATE hotels SET booked = B'1' WHERE id = $1; + --- + kind: tools + name: update-hotel + type: postgres-sql + source: my-pg-source + description: >- + Update a hotel's check-in and check-out dates by its ID. Returns a message + indicating whether the hotel was successfully updated or not. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to update. + - name: checkin_date + type: string + description: The new check-in date of the hotel. + - name: checkout_date + type: string + description: The new check-out date of the hotel. + statement: >- + UPDATE hotels SET checkin_date = CAST($2 as date), checkout_date = CAST($3 + as date) WHERE id = $1; + --- + kind: tools + name: cancel-hotel + type: postgres-sql + source: my-pg-source + description: Cancel a hotel by its ID. + parameters: + - name: hotel_id + type: string + description: The ID of the hotel to cancel. + statement: UPDATE hotels SET booked = B'0' WHERE id = $1; + --- + kind: toolsets + name: my-toolset tools: - search-hotels-by-name: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM hotels WHERE name ILIKE '%' || $1 || '%'; - search-hotels-by-location: - kind: postgres-sql - source: my-pg-source - description: Search for hotels based on location. - parameters: - - name: location - type: string - description: The location of the hotel. - statement: SELECT * FROM hotels WHERE location ILIKE '%' || $1 || '%'; - book-hotel: - kind: postgres-sql - source: my-pg-source - description: >- - Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to book. - statement: UPDATE hotels SET booked = B'1' WHERE id = $1; - update-hotel: - kind: postgres-sql - source: my-pg-source - description: >- - Update a hotel's check-in and check-out dates by its ID. Returns a message - indicating whether the hotel was successfully updated or not. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to update. - - name: checkin_date - type: string - description: The new check-in date of the hotel. - - name: checkout_date - type: string - description: The new check-out date of the hotel. - statement: >- - UPDATE hotels SET checkin_date = CAST($2 as date), checkout_date = CAST($3 - as date) WHERE id = $1; - cancel-hotel: - kind: postgres-sql - source: my-pg-source - description: Cancel a hotel by its ID. - parameters: - - name: hotel_id - type: string - description: The ID of the hotel to cancel. - statement: UPDATE hotels SET booked = B'0' WHERE id = $1; - toolsets: - my-toolset: - - search-hotels-by-name - - search-hotels-by-location - - book-hotel - - update-hotel - - cancel-hotel + - search-hotels-by-name + - search-hotels-by-location + - book-hotel + - update-hotel + - cancel-hotel ``` For more info on tools, check out the `Resources` section of the docs. diff --git a/docs/en/resources/authServices/_index.md b/docs/en/resources/authServices/_index.md index 757b58a1a35a..a40ce182d15f 100644 --- a/docs/en/resources/authServices/_index.md +++ b/docs/en/resources/authServices/_index.md @@ -28,17 +28,19 @@ The following configurations are placed at the top level of a `tools.yaml` file. {{< notice tip >}} If you are accessing Toolbox with multiple applications, each application should register their own Client ID even if they use the same - "kind" of auth provider. + "type" of auth provider. {{< /notice >}} ```yaml -authServices: - my_auth_app_1: - kind: google - clientId: ${YOUR_CLIENT_ID_1} - my_auth_app_2: - kind: google - clientId: ${YOUR_CLIENT_ID_2} +kind: authServices +name: my_auth_app_1 +type: google +clientId: ${YOUR_CLIENT_ID_1} +--- +kind: authServices +name: my_auth_app_2 +type: google +clientId: ${YOUR_CLIENT_ID_2} ``` {{< notice tip >}} diff --git a/docs/en/resources/authServices/google.md b/docs/en/resources/authServices/google.md index b0950040d3b7..f44284731ee9 100644 --- a/docs/en/resources/authServices/google.md +++ b/docs/en/resources/authServices/google.md @@ -40,10 +40,10 @@ id-token][provided-claims] can be used for the parameter. ## Example ```yaml -authServices: - my-google-auth: - kind: google - clientId: ${YOUR_GOOGLE_CLIENT_ID} +kind: authServices +name: my-google-auth +type: google +clientId: ${YOUR_GOOGLE_CLIENT_ID} ``` {{< notice tip >}} @@ -55,5 +55,5 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|------------------------------------------------------------------| -| kind | string | true | Must be "google". | +| type | string | true | Must be "google". | | clientId | string | true | Client ID of your application from registering your application. | diff --git a/docs/en/resources/embeddingModels/_index.md b/docs/en/resources/embeddingModels/_index.md index d9da2b71c3c1..8fb867306fcc 100644 --- a/docs/en/resources/embeddingModels/_index.md +++ b/docs/en/resources/embeddingModels/_index.md @@ -54,12 +54,12 @@ ${ENV_NAME} instead of hardcoding your API keys into the configuration file. Define an embedding model in the `embeddingModels` section: ```yaml -embeddingModels: - gemini-model: # Name of the embedding model - kind: gemini - model: gemini-embedding-001 - apiKey: ${GOOGLE_API_KEY} - dimension: 768 +kind: embeddingModels +name: gemini-model # Name of the embedding model +type: gemini +model: gemini-embedding-001 +apiKey: ${GOOGLE_API_KEY} +dimension: 768 ``` ### Step 2 - Embed Tool Parameters @@ -68,38 +68,39 @@ Use the defined embedding model, embed your query parameters using the `embeddedBy` field. Only string-typed parameters can be embedded: ```yaml -tools: - # Vector ingestion tool - insert_embedding: - kind: postgres-sql - source: my-pg-instance - statement: | - INSERT INTO documents (content, embedding) - VALUES ($1, $2); - parameters: - - name: content - type: string - description: The raw text content to be stored in the database. - - name: vector_string - type: string - # This parameter is hidden from the LLM. - # It automatically copies the value from 'content' and embeds it. - valueFromParam: content - embeddedBy: gemini-model - - # Semantic search tool - search_embedding: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT id, content, embedding <-> $1 AS distance - FROM documents - ORDER BY distance LIMIT 1 - parameters: - - name: semantic_search_string - type: string - description: The search query that will be converted to a vector. - embeddedBy: gemini-model # refers to the name of a defined embedding model +# Vector ingestion tool +kind: tools +name: insert_embedding +type: postgres-sql +source: my-pg-instance +statement: | + INSERT INTO documents (content, embedding) + VALUES ($1, $2); +parameters: + - name: content + type: string + description: The raw text content to be stored in the database. + - name: vector_string + type: string + # This parameter is hidden from the LLM. + # It automatically copies the value from 'content' and embeds it. + valueFromParam: content + embeddedBy: gemini-model +--- +# Semantic search tool +kind: tools +name: search_embedding +type: postgres-sql +source: my-pg-instance +statement: | + SELECT id, content, embedding <-> $1 AS distance + FROM documents + ORDER BY distance LIMIT 1 +parameters: + - name: semantic_search_string + type: string + description: The search query that will be converted to a vector. + embeddedBy: gemini-model # refers to the name of a defined embedding model ``` ## Kinds of Embedding Models diff --git a/docs/en/resources/embeddingModels/gemini.md b/docs/en/resources/embeddingModels/gemini.md index 8fcf8cf358c7..7555c91f85d6 100644 --- a/docs/en/resources/embeddingModels/gemini.md +++ b/docs/en/resources/embeddingModels/gemini.md @@ -50,12 +50,12 @@ information. ## Example ```yaml -embeddingModels: - gemini-model: - kind: gemini - model: gemini-embedding-001 - apiKey: ${GOOGLE_API_KEY} - dimension: 768 +kind: embeddingModels +name: gemini-model +type: gemini +model: gemini-embedding-001 +apiKey: ${GOOGLE_API_KEY} +dimension: 768 ``` {{< notice tip >}} @@ -67,7 +67,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------------------------| -| kind | string | true | Must be `gemini`. | +| type | string | true | Must be `gemini`. | | model | string | true | The Gemini model ID to use (e.g., `gemini-embedding-001`). | | apiKey | string | false | Your API Key from Google AI Studio. | | dimension | integer | false | The number of dimensions in the output vector (e.g., `768`). | diff --git a/docs/en/resources/prompts/_index.md b/docs/en/resources/prompts/_index.md index 5227ba847060..b62f8d17aeca 100644 --- a/docs/en/resources/prompts/_index.md +++ b/docs/en/resources/prompts/_index.md @@ -16,14 +16,14 @@ can be sent to a Large Language Model (LLM). The Toolbox server implements the specification, allowing clients to discover and retrieve these prompts. ```yaml -prompts: - code_review: - description: "Asks the LLM to analyze code quality and suggest improvements." - messages: - - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" - arguments: - - name: "code" - description: "The code to review" +kind: prompts +name: code_review +description: "Asks the LLM to analyze code quality and suggest improvements." +messages: + - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" +arguments: + - name: "code" + description: "The code to review" ``` ## Prompt Schema @@ -31,7 +31,7 @@ prompts: | **field** | **type** | **required** | **description** | |-------------|--------------------------------|--------------|--------------------------------------------------------------------------| | description | string | No | A brief explanation of what the prompt does. | -| kind | string | No | The kind of prompt. Defaults to `"custom"`. | +| type | string | No | The type of prompt. Defaults to `"custom"`. | | messages | [][Message](#message-schema) | Yes | A list of one or more message objects that make up the prompt's content. | | arguments | [][Argument](#argument-schema) | No | A list of arguments that can be interpolated into the prompt's content. | diff --git a/docs/en/resources/prompts/custom/_index.md b/docs/en/resources/prompts/custom/_index.md index 01eedafdbfbf..01a8db4ca9fc 100644 --- a/docs/en/resources/prompts/custom/_index.md +++ b/docs/en/resources/prompts/custom/_index.md @@ -17,14 +17,14 @@ Here is an example of a simple prompt that takes a single argument, code, and asks an LLM to review it. ```yaml -prompts: - code_review: - description: "Asks the LLM to analyze code quality and suggest improvements." - messages: - - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" - arguments: - - name: "code" - description: "The code to review" +kind: prompts +name: code_review +description: "Asks the LLM to analyze code quality and suggest improvements." +messages: + - content: "Please review the following code for quality, correctness, and potential improvements: \n\n{{.code}}" +arguments: + - name: "code" + description: "The code to review" ``` ### Multi-message prompt @@ -33,19 +33,19 @@ You can define prompts with multiple messages to set up more complex conversational contexts, like a role-playing scenario. ```yaml -prompts: - roleplay_scenario: - description: "Sets up a roleplaying scenario with initial messages." - arguments: - - name: "character" - description: "The character the AI should embody." - - name: "situation" - description: "The initial situation for the roleplay." - messages: - - role: "user" - content: "Let's roleplay. You are {{.character}}. The situation is: {{.situation}}" - - role: "assistant" - content: "Okay, I understand. I am ready. What happens next?" +kind: prompts +name: roleplay_scenario +description: "Sets up a roleplaying scenario with initial messages." +arguments: + - name: "character" + description: "The character the AI should embody." + - name: "situation" + description: "The initial situation for the roleplay." +messages: + - role: "user" + content: "Let's roleplay. You are {{.character}}. The situation is: {{.situation}}" + - role: "assistant" + content: "Okay, I understand. I am ready. What happens next?" ``` ## Reference @@ -54,7 +54,7 @@ prompts: | **field** | **type** | **required** | **description** | |-------------|--------------------------------|--------------|--------------------------------------------------------------------------| -| kind | string | No | The kind of prompt. Must be `"custom"`. | +| type | string | No | The type of prompt. Must be `"custom"`. | | description | string | No | A brief explanation of what the prompt does. | | messages | [][Message](#message-schema) | Yes | A list of one or more message objects that make up the prompt's content. | | arguments | [][Argument](#argument-schema) | No | A list of arguments that can be interpolated into the prompt's content. | diff --git a/docs/en/resources/sources/_index.md b/docs/en/resources/sources/_index.md index a5f916726f6a..21d281f6a36f 100644 --- a/docs/en/resources/sources/_index.md +++ b/docs/en/resources/sources/_index.md @@ -17,15 +17,15 @@ instead of hardcoding your secrets into the configuration file. {{< /notice >}} ```yaml -sources: - my-cloud-sql-source: - kind: cloud-sql-postgres - project: my-project-id - region: us-central1 - instance: my-instance-name - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} +kind: sources +name: my-cloud-sql-source +type: cloud-sql-postgres +project: my-project-id +region: us-central1 +instance: my-instance-name +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} ``` In implementation, each source is a different connection pool or client that used diff --git a/docs/en/resources/sources/alloydb-admin.md b/docs/en/resources/sources/alloydb-admin.md index cddff475336b..0584994ab1da 100644 --- a/docs/en/resources/sources/alloydb-admin.md +++ b/docs/en/resources/sources/alloydb-admin.md @@ -25,19 +25,20 @@ Authentication can be handled in two ways: ## Example ```yaml -sources: - my-alloydb-admin: - kind: alloy-admin - - my-oauth-alloydb-admin: - kind: alloydb-admin - useClientOAuth: true +kind: sources +name: my-alloydb-admin +type: alloydb-admin +--- +kind: sources +name: my-oauth-alloydb-admin +type: alloydb-admin +useClientOAuth: true ``` ## Reference | **field** | **type** | **required** | **description** | | -------------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "alloydb-admin". | +| type | string | true | Must be "alloydb-admin". | | defaultProject | string | false | The Google Cloud project ID to use for AlloyDB infrastructure tools. | | useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. | diff --git a/docs/en/resources/sources/alloydb-pg.md b/docs/en/resources/sources/alloydb-pg.md index 2fa502aaec81..cf6d848ae63e 100644 --- a/docs/en/resources/sources/alloydb-pg.md +++ b/docs/en/resources/sources/alloydb-pg.md @@ -176,17 +176,17 @@ To connect using IAM authentication: ## Example ```yaml -sources: - my-alloydb-pg-source: - kind: alloydb-postgres - project: my-project-id - region: us-central1 - cluster: my-cluster - instance: my-instance - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # ipType: "public" +kind: sources +name: my-alloydb-pg-source +type: alloydb-postgres +project: my-project-id +region: us-central1 +cluster: my-cluster +instance: my-instance +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# ipType: "public" ``` {{< notice tip >}} @@ -198,7 +198,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "alloydb-postgres". | +| type | string | true | Must be "alloydb-postgres". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | region | string | true | Name of the GCP region that the cluster was created in (e.g. "us-central1"). | | cluster | string | true | Name of the AlloyDB cluster (e.g. "my-cluster"). | diff --git a/docs/en/resources/sources/bigquery.md b/docs/en/resources/sources/bigquery.md index 8cb05ccbb80b..b898f9f3830a 100644 --- a/docs/en/resources/sources/bigquery.md +++ b/docs/en/resources/sources/bigquery.md @@ -121,47 +121,47 @@ identity used has been granted the correct IAM permissions. Initialize a BigQuery source that uses ADC: ```yaml -sources: - my-bigquery-source: - kind: "bigquery" - project: "my-project-id" - # location: "US" # Optional: Specifies the location for query jobs. - # writeMode: "allowed" # One of: allowed, blocked, protected. Defaults to "allowed". - # allowedDatasets: # Optional: Restricts tool access to a specific list of datasets. - # - "my_dataset_1" - # - "other_project.my_dataset_2" - # impersonateServiceAccount: "service-account@project-id.iam.gserviceaccount.com" # Optional: Service account to impersonate - # scopes: # Optional: List of OAuth scopes to request. - # - "https://www.googleapis.com/auth/bigquery" - # - "https://www.googleapis.com/auth/drive.readonly" - # maxQueryResultRows: 50 # Optional: Limits the number of rows returned by queries. Defaults to 50. +kind: sources +name: my-bigquery-source +type: "bigquery" +project: "my-project-id" +# location: "US" # Optional: Specifies the location for query jobs. +# writeMode: "allowed" # One of: allowed, blocked, protected. Defaults to "allowed". +# allowedDatasets: # Optional: Restricts tool access to a specific list of datasets. +# - "my_dataset_1" +# - "other_project.my_dataset_2" +# impersonateServiceAccount: "service-account@project-id.iam.gserviceaccount.com" # Optional: Service account to impersonate +# scopes: # Optional: List of OAuth scopes to request. +# - "https://www.googleapis.com/auth/bigquery" +# - "https://www.googleapis.com/auth/drive.readonly" +# maxQueryResultRows: 50 # Optional: Limits the number of rows returned by queries. Defaults to 50. ``` Initialize a BigQuery source that uses the client's access token: ```yaml -sources: - my-bigquery-client-auth-source: - kind: "bigquery" - project: "my-project-id" - useClientOAuth: true - # location: "US" # Optional: Specifies the location for query jobs. - # writeMode: "allowed" # One of: allowed, blocked, protected. Defaults to "allowed". - # allowedDatasets: # Optional: Restricts tool access to a specific list of datasets. - # - "my_dataset_1" - # - "other_project.my_dataset_2" - # impersonateServiceAccount: "service-account@project-id.iam.gserviceaccount.com" # Optional: Service account to impersonate - # scopes: # Optional: List of OAuth scopes to request. - # - "https://www.googleapis.com/auth/bigquery" - # - "https://www.googleapis.com/auth/drive.readonly" - # maxQueryResultRows: 50 # Optional: Limits the number of rows returned by queries. Defaults to 50. +kind: sources +name: my-bigquery-client-auth-source +type: "bigquery" +project: "my-project-id" +useClientOAuth: true +# location: "US" # Optional: Specifies the location for query jobs. +# writeMode: "allowed" # One of: allowed, blocked, protected. Defaults to "allowed". +# allowedDatasets: # Optional: Restricts tool access to a specific list of datasets. +# - "my_dataset_1" +# - "other_project.my_dataset_2" +# impersonateServiceAccount: "service-account@project-id.iam.gserviceaccount.com" # Optional: Service account to impersonate +# scopes: # Optional: List of OAuth scopes to request. +# - "https://www.googleapis.com/auth/bigquery" +# - "https://www.googleapis.com/auth/drive.readonly" +# maxQueryResultRows: 50 # Optional: Limits the number of rows returned by queries. Defaults to 50. ``` ## Reference | **field** | **type** | **required** | **description** | |---------------------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery". | +| type | string | true | Must be "bigquery". | | project | string | true | Id of the Google Cloud project to use for billing and as the default project for BigQuery resources. | | location | string | false | Specifies the location (e.g., 'us', 'asia-northeast1') in which to run the query job. This location must match the location of any tables referenced in the query. Defaults to the table's location or 'US' if the location cannot be determined. [Learn More](https://cloud.google.com/bigquery/docs/locations) | | writeMode | string | false | Controls the write behavior for tools. `allowed` (default): All queries are permitted. `blocked`: Only `SELECT` statements are allowed for the `bigquery-execute-sql` tool. `protected`: Enables session-based execution where all tools associated with this source instance share the same [BigQuery session](https://cloud.google.com/bigquery/docs/sessions-intro). This allows for stateful operations using temporary tables (e.g., `CREATE TEMP TABLE`). For `bigquery-execute-sql`, `SELECT` statements can be used on all tables, but write operations are restricted to the session's temporary dataset. For tools like `bigquery-sql`, `bigquery-forecast`, and `bigquery-analyze-contribution`, the `writeMode` restrictions do not apply, but they will operate within the shared session. **Note:** The `protected` mode cannot be used with `useClientOAuth: true`. It is also not recommended for multi-user server environments, as all users would share the same session. A session is terminated automatically after 24 hours of inactivity or after 7 days, whichever comes first. A new session is created on the next request, and any temporary data from the previous session will be lost. | diff --git a/docs/en/resources/sources/bigtable.md b/docs/en/resources/sources/bigtable.md index e05653ac05a4..7e4207e9c590 100644 --- a/docs/en/resources/sources/bigtable.md +++ b/docs/en/resources/sources/bigtable.md @@ -59,17 +59,17 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -sources: - my-bigtable-source: - kind: "bigtable" - project: "my-project-id" - instance: "test-instance" +kind: sources +name: my-bigtable-source +type: "bigtable" +project: "my-project-id" +instance: "test-instance" ``` ## Reference | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|-------------------------------------------------------------------------------| -| kind | string | true | Must be "bigtable". | +| type | string | true | Must be "bigtable". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | instance | string | true | Name of the Bigtable instance. | diff --git a/docs/en/resources/sources/cassandra.md b/docs/en/resources/sources/cassandra.md index 6a149718b452..1009a2bce0d2 100644 --- a/docs/en/resources/sources/cassandra.md +++ b/docs/en/resources/sources/cassandra.md @@ -23,19 +23,19 @@ distributed architectures, and a flexible approach to schema definition. ## Example ```yaml -sources: - my-cassandra-source: - kind: cassandra - hosts: - - 127.0.0.1 - keyspace: my_keyspace - protoVersion: 4 - username: ${USER_NAME} - password: ${PASSWORD} - caPath: /path/to/ca.crt # Optional: path to CA certificate - certPath: /path/to/client.crt # Optional: path to client certificate - keyPath: /path/to/client.key # Optional: path to client key - enableHostVerification: true # Optional: enable host verification +kind: sources +name: my-cassandra-source +type: cassandra +hosts: + - 127.0.0.1 +keyspace: my_keyspace +protoVersion: 4 +username: ${USER_NAME} +password: ${PASSWORD} +caPath: /path/to/ca.crt # Optional: path to CA certificate +certPath: /path/to/client.crt # Optional: path to client certificate +keyPath: /path/to/client.key # Optional: path to client key +enableHostVerification: true # Optional: enable host verification ``` {{< notice tip >}} @@ -47,7 +47,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |------------------------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cassandra". | +| type | string | true | Must be "cassandra". | | hosts | string[] | true | List of IP addresses to connect to (e.g., ["192.168.1.1:9042", "192.168.1.2:9042","192.168.1.3:9042"]). The default port is 9042 if not specified. | | keyspace | string | true | Name of the Cassandra keyspace to connect to (e.g., "my_keyspace"). | | protoVersion | integer | false | Protocol version for the Cassandra connection (e.g., 4). | diff --git a/docs/en/resources/sources/clickhouse.md b/docs/en/resources/sources/clickhouse.md index 2442899ce52d..378e52b22c35 100644 --- a/docs/en/resources/sources/clickhouse.md +++ b/docs/en/resources/sources/clickhouse.md @@ -46,31 +46,31 @@ ClickHouse supports multiple protocols: ### Secure Connection Example ```yaml -sources: - secure-clickhouse-source: - kind: clickhouse - host: clickhouse.example.com - port: "8443" - database: analytics - user: ${CLICKHOUSE_USER} - password: ${CLICKHOUSE_PASSWORD} - protocol: https - secure: true +kind: sources +name: secure-clickhouse-source +type: clickhouse +host: clickhouse.example.com +port: "8443" +database: analytics +user: ${CLICKHOUSE_USER} +password: ${CLICKHOUSE_PASSWORD} +protocol: https +secure: true ``` ### HTTP Protocol Example ```yaml -sources: - http-clickhouse-source: - kind: clickhouse - host: localhost - port: "8123" - database: logs - user: ${CLICKHOUSE_USER} - password: ${CLICKHOUSE_PASSWORD} - protocol: http - secure: false +kind: sources +name: http-clickhouse-source +type: clickhouse +host: localhost +port: "8123" +database: logs +user: ${CLICKHOUSE_USER} +password: ${CLICKHOUSE_PASSWORD} +protocol: http +secure: false ``` {{< notice tip >}} @@ -82,7 +82,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|-------------------------------------------------------------------------------------| -| kind | string | true | Must be "clickhouse". | +| type | string | true | Must be "clickhouse". | | host | string | true | IP address or hostname to connect to (e.g. "127.0.0.1" or "clickhouse.example.com") | | port | string | true | Port to connect to (e.g. "8443" for HTTPS, "8123" for HTTP) | | database | string | true | Name of the ClickHouse database to connect to (e.g. "my_database"). | diff --git a/docs/en/resources/sources/cloud-gda.md b/docs/en/resources/sources/cloud-gda.md index dc400f17e873..5d65df3cb73c 100644 --- a/docs/en/resources/sources/cloud-gda.md +++ b/docs/en/resources/sources/cloud-gda.md @@ -20,21 +20,22 @@ Authentication can be handled in two ways: ## Example ```yaml -sources: - my-gda-source: - kind: cloud-gemini-data-analytics - projectId: my-project-id - - my-oauth-gda-source: - kind: cloud-gemini-data-analytics - projectId: my-project-id - useClientOAuth: true +kind: sources +name: my-gda-source +type: cloud-gemini-data-analytics +projectId: my-project-id +--- +kind: sources +name: my-oauth-gda-source +type: cloud-gemini-data-analytics +projectId: my-project-id +useClientOAuth: true ``` ## Reference | **field** | **type** | **required** | **description** | | -------------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "cloud-gemini-data-analytics". | +| type | string | true | Must be "cloud-gemini-data-analytics". | | projectId | string | true | The Google Cloud Project ID where the API is enabled. | | useClientOAuth | boolean | false | If true, the source uses the token provided by the caller (forwarded to the API). Otherwise, it uses server-side Application Default Credentials (ADC). Defaults to `false`. | diff --git a/docs/en/resources/sources/cloud-healthcare.md b/docs/en/resources/sources/cloud-healthcare.md index 117079688a23..b1bf3d6c356f 100644 --- a/docs/en/resources/sources/cloud-healthcare.md +++ b/docs/en/resources/sources/cloud-healthcare.md @@ -123,41 +123,41 @@ identity used has been granted the correct IAM permissions. Initialize a Cloud Healthcare API source that uses ADC: ```yaml -sources: - my-healthcare-source: - kind: "cloud-healthcare" - project: "my-project-id" - region: "us-central1" - dataset: "my-healthcare-dataset-id" - # allowedFhirStores: # Optional: Restricts tool access to a specific list of FHIR store IDs. - # - "my_fhir_store_1" - # allowedDicomStores: # Optional: Restricts tool access to a specific list of DICOM store IDs. - # - "my_dicom_store_1" - # - "my_dicom_store_2" +kind: sources +name: my-healthcare-source +type: "cloud-healthcare" +project: "my-project-id" +region: "us-central1" +dataset: "my-healthcare-dataset-id" +# allowedFhirStores: # Optional: Restricts tool access to a specific list of FHIR store IDs. +# - "my_fhir_store_1" +# allowedDicomStores: # Optional: Restricts tool access to a specific list of DICOM store IDs. +# - "my_dicom_store_1" +# - "my_dicom_store_2" ``` Initialize a Cloud Healthcare API source that uses the client's access token: ```yaml -sources: - my-healthcare-client-auth-source: - kind: "cloud-healthcare" - project: "my-project-id" - region: "us-central1" - dataset: "my-healthcare-dataset-id" - useClientOAuth: true - # allowedFhirStores: # Optional: Restricts tool access to a specific list of FHIR store IDs. - # - "my_fhir_store_1" - # allowedDicomStores: # Optional: Restricts tool access to a specific list of DICOM store IDs. - # - "my_dicom_store_1" - # - "my_dicom_store_2" +kind: sources +name: my-healthcare-client-auth-source +type: "cloud-healthcare" +project: "my-project-id" +region: "us-central1" +dataset: "my-healthcare-dataset-id" +useClientOAuth: true +# allowedFhirStores: # Optional: Restricts tool access to a specific list of FHIR store IDs. +# - "my_fhir_store_1" +# allowedDicomStores: # Optional: Restricts tool access to a specific list of DICOM store IDs. +# - "my_dicom_store_1" +# - "my_dicom_store_2" ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------:|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare". | +| type | string | true | Must be "cloud-healthcare". | | project | string | true | ID of the GCP project that the dataset lives in. | | region | string | true | Specifies the region (e.g., 'us', 'asia-northeast1') of the healthcare dataset. [Learn More](https://cloud.google.com/healthcare-api/docs/regions) | | dataset | string | true | ID of the healthcare dataset. | diff --git a/docs/en/resources/sources/cloud-monitoring.md b/docs/en/resources/sources/cloud-monitoring.md index 84b700721fbb..dc4847549a9a 100644 --- a/docs/en/resources/sources/cloud-monitoring.md +++ b/docs/en/resources/sources/cloud-monitoring.md @@ -25,18 +25,19 @@ Authentication can be handled in two ways: ## Example ```yaml -sources: - my-cloud-monitoring: - kind: cloud-monitoring - - my-oauth-cloud-monitoring: - kind: cloud-monitoring - useClientOAuth: true +kind: sources +name: my-cloud-monitoring +type: cloud-monitoring +--- +kind: sources +name: my-oauth-cloud-monitoring +type: cloud-monitoring +useClientOAuth: true ``` ## Reference | **field** | **type** | **required** | **description** | |----------------|:--------:|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cloud-monitoring". | +| type | string | true | Must be "cloud-monitoring". | | useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. | diff --git a/docs/en/resources/sources/cloud-sql-admin.md b/docs/en/resources/sources/cloud-sql-admin.md index e66448725e4a..51462e982d85 100644 --- a/docs/en/resources/sources/cloud-sql-admin.md +++ b/docs/en/resources/sources/cloud-sql-admin.md @@ -24,19 +24,20 @@ Authentication can be handled in two ways: ## Example ```yaml -sources: - my-cloud-sql-admin: - kind: cloud-sql-admin - - my-oauth-cloud-sql-admin: - kind: cloud-sql-admin - useClientOAuth: true +kind: sources +name: my-cloud-sql-admin +type: cloud-sql-admin +--- +kind: sources +name: my-oauth-cloud-sql-admin +type: cloud-sql-admin +useClientOAuth: true ``` ## Reference | **field** | **type** | **required** | **description** | | -------------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "cloud-sql-admin". | +| type | string | true | Must be "cloud-sql-admin". | | defaultProject | string | false | The Google Cloud project ID to use for Cloud SQL infrastructure tools. | | useClientOAuth | boolean | false | If true, the source will use client-side OAuth for authorization. Otherwise, it will use Application Default Credentials. Defaults to `false`. | diff --git a/docs/en/resources/sources/cloud-sql-mssql.md b/docs/en/resources/sources/cloud-sql-mssql.md index 9477e44c9385..ef3ce3cebed3 100644 --- a/docs/en/resources/sources/cloud-sql-mssql.md +++ b/docs/en/resources/sources/cloud-sql-mssql.md @@ -87,16 +87,16 @@ Currently, this source only uses standard authentication. You will need to ## Example ```yaml -sources: - my-cloud-sql-mssql-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # ipType: private +kind: sources +name: my-cloud-sql-mssql-instance +type: cloud-sql-mssql +project: my-project +region: my-region +instance: my-instance +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# ipType: private ``` {{< notice tip >}} @@ -108,7 +108,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cloud-sql-mssql". | +| type | string | true | Must be "cloud-sql-mssql". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | region | string | true | Name of the GCP region that the cluster was created in (e.g. "us-central1"). | | instance | string | true | Name of the Cloud SQL instance within the cluster (e.g. "my-instance"). | diff --git a/docs/en/resources/sources/cloud-sql-mysql.md b/docs/en/resources/sources/cloud-sql-mysql.md index e9f89f22a980..ba0c1b1f26a9 100644 --- a/docs/en/resources/sources/cloud-sql-mysql.md +++ b/docs/en/resources/sources/cloud-sql-mysql.md @@ -128,16 +128,16 @@ To connect using IAM authentication: ## Example ```yaml -sources: - my-cloud-sql-mysql-source: - kind: cloud-sql-mysql - project: my-project-id - region: us-central1 - instance: my-instance - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # ipType: "private" +kind: sources +name: my-cloud-sql-mysql-source +type: cloud-sql-mysql +project: my-project-id +region: us-central1 +instance: my-instance +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# ipType: "private" ``` {{< notice tip >}} @@ -149,7 +149,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cloud-sql-mysql". | +| type | string | true | Must be "cloud-sql-mysql". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | region | string | true | Name of the GCP region that the cluster was created in (e.g. "us-central1"). | | instance | string | true | Name of the Cloud SQL instance within the cluster (e.g. "my-instance"). | diff --git a/docs/en/resources/sources/cloud-sql-pg.md b/docs/en/resources/sources/cloud-sql-pg.md index 2ecdcee6acb5..3b5f54781d7a 100644 --- a/docs/en/resources/sources/cloud-sql-pg.md +++ b/docs/en/resources/sources/cloud-sql-pg.md @@ -178,16 +178,16 @@ To connect using IAM authentication: ## Example ```yaml -sources: - my-cloud-sql-pg-source: - kind: cloud-sql-postgres - project: my-project-id - region: us-central1 - instance: my-instance - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # ipType: "private" +kind: sources +name: my-cloud-sql-pg-source +type: cloud-sql-postgres +project: my-project-id +region: us-central1 +instance: my-instance +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# ipType: "private" ``` {{< notice tip >}} @@ -199,7 +199,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cloud-sql-postgres". | +| type | string | true | Must be "cloud-sql-postgres". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | region | string | true | Name of the GCP region that the cluster was created in (e.g. "us-central1"). | | instance | string | true | Name of the Cloud SQL instance within the cluster (e.g. "my-instance"). | diff --git a/docs/en/resources/sources/couchbase.md b/docs/en/resources/sources/couchbase.md index b571d11cfee4..18703f68b878 100644 --- a/docs/en/resources/sources/couchbase.md +++ b/docs/en/resources/sources/couchbase.md @@ -19,14 +19,14 @@ allowing tools to execute SQL queries against it. ## Example ```yaml -sources: - my-couchbase-instance: - kind: couchbase - connectionString: couchbase://localhost - bucket: travel-sample - scope: inventory - username: Administrator - password: password +kind: sources +name: my-couchbase-instance +type: couchbase +connectionString: couchbase://localhost +bucket: travel-sample +scope: inventory +username: Administrator +password: password ``` {{< notice note >}} @@ -38,7 +38,7 @@ Connections](https://docs.couchbase.com/java-sdk/current/howtos/managing-connect | **field** | **type** | **required** | **description** | |----------------------|:--------:|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "couchbase". | +| type | string | true | Must be "couchbase". | | connectionString | string | true | Connection string for the Couchbase cluster. | | bucket | string | true | Name of the bucket to connect to. | | scope | string | true | Name of the scope within the bucket. | diff --git a/docs/en/resources/sources/dataplex.md b/docs/en/resources/sources/dataplex.md index 828ee5b6985b..52c44166f5e2 100644 --- a/docs/en/resources/sources/dataplex.md +++ b/docs/en/resources/sources/dataplex.md @@ -23,10 +23,10 @@ applying artificial intelligence and machine learning. ## Example ```yaml -sources: - my-dataplex-source: - kind: "dataplex" - project: "my-project-id" +kind: sources +name: my-dataplex-source +type: "dataplex" +project: "my-project-id" ``` ## Sample System Prompt @@ -355,5 +355,5 @@ This abbreviated syntax works for the qualified predicates except for `label` in | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|----------------------------------------------------------------------------------| -| kind | string | true | Must be "dataplex". | +| type | string | true | Must be "dataplex". | | project | string | true | ID of the GCP project used for quota and billing purposes (e.g. "my-project-id").| diff --git a/docs/en/resources/sources/dgraph.md b/docs/en/resources/sources/dgraph.md index 8ac82e03c487..e99721b73c1b 100644 --- a/docs/en/resources/sources/dgraph.md +++ b/docs/en/resources/sources/dgraph.md @@ -51,14 +51,14 @@ and user credentials for that namespace. ## Example ```yaml -sources: - my-dgraph-source: - kind: dgraph - dgraphUrl: https://xxxx.cloud.dgraph.io - user: ${USER_NAME} - password: ${PASSWORD} - apiKey: ${API_KEY} - namespace : 0 +kind: sources +name: my-dgraph-source +type: dgraph +dgraphUrl: https://xxxx.cloud.dgraph.io +user: ${USER_NAME} +password: ${PASSWORD} +apiKey: ${API_KEY} +namespace : 0 ``` {{< notice tip >}} @@ -70,7 +70,7 @@ instead of hardcoding your secrets into the configuration file. | **Field** | **Type** | **Required** | **Description** | |-------------|:--------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "dgraph". | +| type | string | true | Must be "dgraph". | | dgraphUrl | string | true | Connection URI (e.g. "", ""). | | user | string | false | Name of the Dgraph user to connect as (e.g., "groot"). | | password | string | false | Password of the Dgraph user (e.g., "password"). | diff --git a/docs/en/resources/sources/elasticsearch.md b/docs/en/resources/sources/elasticsearch.md index d0451c16b14c..57527e6800bd 100644 --- a/docs/en/resources/sources/elasticsearch.md +++ b/docs/en/resources/sources/elasticsearch.md @@ -59,18 +59,18 @@ applying permissions to an API key. ## Example ```yaml -sources: - my-elasticsearch-source: - kind: "elasticsearch" - addresses: - - "http://localhost:9200" - apikey: "my-api-key" +kind: sources +name: my-elasticsearch-source +type: "elasticsearch" +addresses: + - "http://localhost:9200" +apikey: "my-api-key" ``` ## Reference | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------| -| kind | string | true | Must be "elasticsearch". | +| type | string | true | Must be "elasticsearch". | | addresses | []string | true | List of Elasticsearch hosts to connect to. | | apikey | string | true | The API key to use for authentication. | diff --git a/docs/en/resources/sources/firebird.md b/docs/en/resources/sources/firebird.md index 1c3a8a7696ee..fe7a1003a1ea 100644 --- a/docs/en/resources/sources/firebird.md +++ b/docs/en/resources/sources/firebird.md @@ -36,14 +36,14 @@ user][fb-users] to login to the database with. ## Example ```yaml -sources: - my_firebird_db: - kind: firebird - host: "localhost" - port: 3050 - database: "/path/to/your/database.fdb" - user: ${FIREBIRD_USER} - password: ${FIREBIRD_PASS} +kind: sources +name: my_firebird_db +type: firebird +host: "localhost" +port: 3050 +database: "/path/to/your/database.fdb" +user: ${FIREBIRD_USER} +password: ${FIREBIRD_PASS} ``` {{< notice tip >}} @@ -55,7 +55,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|------------------------------------------------------------------------------| -| kind | string | true | Must be "firebird". | +| type | string | true | Must be "firebird". | | host | string | true | IP address to connect to (e.g. "127.0.0.1") | | port | string | true | Port to connect to (e.g. "3050") | | database | string | true | Path to the Firebird database file (e.g. "/var/lib/firebird/data/test.fdb"). | diff --git a/docs/en/resources/sources/firestore.md b/docs/en/resources/sources/firestore.md index 5fe3c875d158..d15a44507d20 100644 --- a/docs/en/resources/sources/firestore.md +++ b/docs/en/resources/sources/firestore.md @@ -61,17 +61,17 @@ database named `(default)` will be used. ## Example ```yaml -sources: - my-firestore-source: - kind: "firestore" - project: "my-project-id" - # database: "my-database" # Optional, defaults to "(default)" +kind: sources +name: my-firestore-source +type: "firestore" +project: "my-project-id" +# database: "my-database" # Optional, defaults to "(default)" ``` ## Reference | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "firestore". | +| type | string | true | Must be "firestore". | | project | string | true | Id of the GCP project that contains the Firestore database (e.g. "my-project-id"). | | database | string | false | Name of the Firestore database to connect to. Defaults to "(default)" if not specified. | diff --git a/docs/en/resources/sources/http.md b/docs/en/resources/sources/http.md index edb25002f8ab..cd840318b80c 100644 --- a/docs/en/resources/sources/http.md +++ b/docs/en/resources/sources/http.md @@ -21,18 +21,18 @@ and other HTTP-accessible resources. ## Example ```yaml -sources: - my-http-source: - kind: http - baseUrl: https://api.example.com/data - timeout: 10s # default to 30s - headers: - Authorization: Bearer ${API_KEY} - Content-Type: application/json - queryParams: - param1: value1 - param2: value2 - # disableSslVerification: false +kind: sources +name: my-http-source +type: http +baseUrl: https://api.example.com/data +timeout: 10s # default to 30s +headers: + Authorization: Bearer ${API_KEY} + Content-Type: application/json +queryParams: + param1: value1 + param2: value2 +# disableSslVerification: false ``` {{< notice tip >}} @@ -44,7 +44,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |------------------------|:-----------------:|:------------:|------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "http". | +| type | string | true | Must be "http". | | baseUrl | string | true | The base URL for the HTTP requests (e.g., `https://api.example.com`). | | timeout | string | false | The timeout for HTTP requests (e.g., "5s", "1m", refer to [ParseDuration][parse-duration-doc] for more examples). Defaults to 30s. | | headers | map[string]string | false | Default headers to include in the HTTP requests. | diff --git a/docs/en/resources/sources/looker.md b/docs/en/resources/sources/looker.md index 75bebf37ea99..d731f0513852 100644 --- a/docs/en/resources/sources/looker.md +++ b/docs/en/resources/sources/looker.md @@ -56,16 +56,16 @@ To initialize the application default credential run `gcloud auth login ## Example ```yaml -sources: - my-looker-source: - kind: looker - base_url: http://looker.example.com - client_id: ${LOOKER_CLIENT_ID} - client_secret: ${LOOKER_CLIENT_SECRET} - project: ${LOOKER_PROJECT} - location: ${LOOKER_LOCATION} - verify_ssl: true - timeout: 600s +kind: sources +name: my-looker-source +type: looker +base_url: http://looker.example.com +client_id: ${LOOKER_CLIENT_ID} +client_secret: ${LOOKER_CLIENT_SECRET} +project: ${LOOKER_PROJECT} +location: ${LOOKER_LOCATION} +verify_ssl: true +timeout: 600s ``` The Looker base url will look like "https://looker.example.com", don't include @@ -93,7 +93,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |----------------------|:--------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "looker". | +| type | string | true | Must be "looker". | | base_url | string | true | The URL of your Looker server with no trailing /. | | client_id | string | false | The client id assigned by Looker. | | client_secret | string | false | The client secret assigned by Looker. | diff --git a/docs/en/resources/sources/mariadb.md b/docs/en/resources/sources/mariadb.md index c956274fde9a..67854f4a3def 100644 --- a/docs/en/resources/sources/mariadb.md +++ b/docs/en/resources/sources/mariadb.md @@ -45,18 +45,18 @@ MariaDB user][mariadb-users] to log in to the database. ## Example ```yaml -sources: - my_mariadb_db: - kind: mysql - host: 127.0.0.1 - port: 3306 - database: my_db - user: ${MARIADB_USER} - password: ${MARIADB_PASS} - # Optional TLS and other driver parameters. For example, enable preferred TLS: - # queryParams: - # tls: preferred - queryTimeout: 30s # Optional: query timeout duration +kind: sources +name: my_mariadb_db +type: mysql +host: 127.0.0.1 +port: 3306 +database: my_db +user: ${MARIADB_USER} +password: ${MARIADB_PASS} +# Optional TLS and other driver parameters. For example, enable preferred TLS: +# queryParams: +# tls: preferred +queryTimeout: 30s # Optional: query timeout duration ``` {{< notice tip >}} @@ -68,7 +68,7 @@ Use environment variables instead of committing credentials to source files. | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | ----------------------------------------------------------------------------------------------- | -| kind | string | true | Must be `mysql`. | +| type | string | true | Must be `mysql`. | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "3307"). | | database | string | true | Name of the MariaDB database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/mindsdb.md b/docs/en/resources/sources/mindsdb.md index 5ea8f4a14791..6ec7e5702132 100644 --- a/docs/en/resources/sources/mindsdb.md +++ b/docs/en/resources/sources/mindsdb.md @@ -125,15 +125,15 @@ can omit the password field. ## Example ```yaml -sources: - my-mindsdb-source: - kind: mindsdb - host: 127.0.0.1 - port: 3306 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} # Optional: omit if MindsDB is configured without authentication - queryTimeout: 30s # Optional: query timeout duration +kind: sources +name: my-mindsdb-source +type: mindsdb +host: 127.0.0.1 +port: 3306 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} # Optional: omit if MindsDB is configured without authentication +queryTimeout: 30s # Optional: query timeout duration ``` ### Working Configuration Example @@ -141,13 +141,13 @@ sources: Here's a working configuration that has been tested: ```yaml -sources: - my-pg-source: - kind: mindsdb - host: 127.0.0.1 - port: 47335 - database: files - user: mindsdb +kind: sources +name: my-pg-source +type: mindsdb +host: 127.0.0.1 +port: 47335 +database: files +user: mindsdb ``` {{< notice tip >}} @@ -176,7 +176,7 @@ With MindsDB integration, you can: | **field** | **type** | **required** | **description** | |--------------|:--------:|:------------:|--------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mindsdb". | +| type | string | true | Must be "mindsdb". | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "3306"). | | database | string | true | Name of the MindsDB database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/mongodb.md b/docs/en/resources/sources/mongodb.md index 91fbe239570d..50e3a63dced8 100644 --- a/docs/en/resources/sources/mongodb.md +++ b/docs/en/resources/sources/mongodb.md @@ -17,10 +17,10 @@ flexible, JSON-like documents, making it easy to develop and scale applications. ## Example ```yaml -sources: - my-mongodb: - kind: mongodb - uri: "mongodb+srv://username:password@host.mongodb.net" +kind: sources +name: my-mongodb +type: mongodb +uri: "mongodb+srv://username:password@host.mongodb.net" ``` @@ -28,5 +28,5 @@ sources: | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|-------------------------------------------------------------------| -| kind | string | true | Must be "mongodb". | +| type | string | true | Must be "mongodb". | | uri | string | true | connection string to connect to MongoDB | diff --git a/docs/en/resources/sources/mssql.md b/docs/en/resources/sources/mssql.md index 424d781c331e..e1b36228ad18 100644 --- a/docs/en/resources/sources/mssql.md +++ b/docs/en/resources/sources/mssql.md @@ -39,15 +39,15 @@ SQL Server user][mssql-users] to login to the database with. ## Example ```yaml -sources: - my-mssql-source: - kind: mssql - host: 127.0.0.1 - port: 1433 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # encrypt: strict +kind: sources +name: my-mssql-source +type: mssql +host: 127.0.0.1 +port: 1433 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# encrypt: strict ``` {{< notice tip >}} @@ -59,7 +59,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mssql". | +| type | string | true | Must be "mssql". | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "1433"). | | database | string | true | Name of the SQL Server database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/mysql.md b/docs/en/resources/sources/mysql.md index 95f2b96d7cc7..ee294bc8ff7c 100644 --- a/docs/en/resources/sources/mysql.md +++ b/docs/en/resources/sources/mysql.md @@ -49,18 +49,18 @@ MySQL user][mysql-users] to login to the database with. ## Example ```yaml -sources: - my-mysql-source: - kind: mysql - host: 127.0.0.1 - port: 3306 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - # Optional TLS and other driver parameters. For example, enable preferred TLS: - # queryParams: - # tls: preferred - queryTimeout: 30s # Optional: query timeout duration +kind: sources +name: my-mysql-source +type: mysql +host: 127.0.0.1 +port: 3306 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +# Optional TLS and other driver parameters. For example, enable preferred TLS: +# queryParams: +# tls: preferred +queryTimeout: 30s # Optional: query timeout duration ``` {{< notice tip >}} @@ -72,7 +72,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | ----------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "mysql". | +| type | string | true | Must be "mysql". | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "3306"). | | database | string | true | Name of the MySQL database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/neo4j.md b/docs/en/resources/sources/neo4j.md index 223915c3371f..0400ea25d594 100644 --- a/docs/en/resources/sources/neo4j.md +++ b/docs/en/resources/sources/neo4j.md @@ -33,13 +33,13 @@ user if available. ## Example ```yaml -sources: - my-neo4j-source: - kind: neo4j - uri: neo4j+s://xxxx.databases.neo4j.io:7687 - user: ${USER_NAME} - password: ${PASSWORD} - database: "neo4j" +kind: sources +name: my-neo4j-source +type: neo4j +uri: neo4j+s://xxxx.databases.neo4j.io:7687 +user: ${USER_NAME} +password: ${PASSWORD} +database: "neo4j" ``` {{< notice tip >}} @@ -51,7 +51,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|----------------------------------------------------------------------| -| kind | string | true | Must be "neo4j". | +| type | string | true | Must be "neo4j". | | uri | string | true | Connect URI ("bolt://localhost", "neo4j+s://xxx.databases.neo4j.io") | | user | string | true | Name of the Neo4j user to connect as (e.g. "neo4j"). | | password | string | true | Password of the Neo4j user (e.g. "my-password"). | diff --git a/docs/en/resources/sources/oceanbase.md b/docs/en/resources/sources/oceanbase.md index b26b46b8beec..24e24f5bfef7 100644 --- a/docs/en/resources/sources/oceanbase.md +++ b/docs/en/resources/sources/oceanbase.md @@ -33,15 +33,15 @@ with SSL). ## Example ```yaml -sources: - my-oceanbase-source: - kind: oceanbase - host: 127.0.0.1 - port: 2881 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - queryTimeout: 30s # Optional: query timeout duration +kind: sources +name: my-oceanbase-source +type: oceanbase +host: 127.0.0.1 +port: 2881 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +queryTimeout: 30s # Optional: query timeout duration ``` {{< notice tip >}} @@ -53,7 +53,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: |-------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "oceanbase". | +| type | string | true | Must be "oceanbase". | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "2881"). | | database | string | true | Name of the OceanBase database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/oracle.md b/docs/en/resources/sources/oracle.md index 51fa18fe1324..8778838cf6ec 100644 --- a/docs/en/resources/sources/oracle.md +++ b/docs/en/resources/sources/oracle.md @@ -90,27 +90,27 @@ using a TNS (Transparent Network Substrate) alias. This example demonstrates the four connection methods you could choose from: ```yaml -sources: - my-oracle-source: - kind: oracle - - # --- Choose one connection method --- - # 1. Host, Port, and Service Name - host: 127.0.0.1 - port: 1521 - serviceName: XEPDB1 - - # 2. Direct Connection String - connectionString: "127.0.0.1:1521/XEPDB1" - - # 3. TNS Alias (requires tnsnames.ora) - tnsAlias: "MY_DB_ALIAS" - tnsAdmin: "/opt/oracle/network/admin" # Optional: overrides TNS_ADMIN env var - - user: ${USER_NAME} - password: ${PASSWORD} - - # Optional: Set to true to use the OCI-based driver for advanced features (Requires Oracle Instant Client) +kind: sources +name: my-oracle-source +type: oracle + +# --- Choose one connection method --- +# 1. Host, Port, and Service Name +host: 127.0.0.1 +port: 1521 +serviceName: XEPDB1 + +# 2. Direct Connection String +connectionString: "127.0.0.1:1521/XEPDB1" + +# 3. TNS Alias (requires tnsnames.ora) +tnsAlias: "MY_DB_ALIAS" +tnsAdmin: "/opt/oracle/network/admin" # Optional: overrides TNS_ADMIN env var + +user: ${USER_NAME} +password: ${PASSWORD} + +# Optional: Set to true to use the OCI-based driver for advanced features (Requires Oracle Instant Client) ``` ### Using an Oracle Wallet @@ -122,15 +122,15 @@ Oracle Wallet allows you to store credentails used for database connection. Depe The `go-ora` driver uses the `walletLocation` field to connect to a database secured with an Oracle Wallet without standard username and password. ```yaml -sources: - pure-go-wallet: - kind: oracle - connectionString: "127.0.0.1:1521/XEPDB1" - user: ${USER_NAME} - password: ${PASSWORD} - # The TNS Alias is often required to connect to a service registered in tnsnames.ora - tnsAlias: "SECURE_DB_ALIAS" - walletLocation: "/path/to/my/wallet/directory" +kind: sources +name: pure-go-wallet +type: oracle +connectionString: "127.0.0.1:1521/XEPDB1" +user: ${USER_NAME} +password: ${PASSWORD} +# The TNS Alias is often required to connect to a service registered in tnsnames.ora +tnsAlias: "SECURE_DB_ALIAS" +walletLocation: "/path/to/my/wallet/directory" ``` #### OCI-Based Driver (`useOCI: true`) - Oracle Wallet @@ -138,15 +138,15 @@ sources: For the OCI-based driver, wallet authentication is triggered by setting tnsAdmin to the wallet directory and connecting via a tnsAlias. ```yaml -sources: - oci-wallet: - kind: oracle - connectionString: "127.0.0.1:1521/XEPDB1" - user: ${USER_NAME} - password: ${PASSWORD} - tnsAlias: "WALLET_DB_ALIAS" - tnsAdmin: "/opt/oracle/wallet" # Directory containing tnsnames.ora, sqlnet.ora, and wallet files - useOCI: true +kind: sources +name: oci-wallet +type: oracle +connectionString: "127.0.0.1:1521/XEPDB1" +user: ${USER_NAME} +password: ${PASSWORD} +tnsAlias: "WALLET_DB_ALIAS" +tnsAdmin: "/opt/oracle/wallet" # Directory containing tnsnames.ora, sqlnet.ora, and wallet files +useOCI: true ``` {{< notice tip >}} @@ -158,7 +158,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |------------------|:--------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "oracle". | +| type | string | true | Must be "oracle". | | user | string | true | Name of the Oracle user to connect as (e.g. "my-oracle-user"). | | password | string | true | Password of the Oracle user (e.g. "my-password"). | | host | string | false | IP address or hostname to connect to (e.g. "127.0.0.1"). Required if not using `connectionString` or `tnsAlias`. | diff --git a/docs/en/resources/sources/postgres.md b/docs/en/resources/sources/postgres.md index 8668b4619027..ed7c77aeee2d 100644 --- a/docs/en/resources/sources/postgres.md +++ b/docs/en/resources/sources/postgres.md @@ -107,14 +107,14 @@ PostgreSQL user][pg-users] to login to the database with. ## Example ```yaml -sources: - my-pg-source: - kind: postgres - host: 127.0.0.1 - port: 5432 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} +kind: sources +name: my-pg-source +type: postgres +host: 127.0.0.1 +port: 5432 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} ``` {{< notice tip >}} @@ -126,7 +126,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-------------|:------------------:|:------------:|------------------------------------------------------------------------| -| kind | string | true | Must be "postgres". | +| type | string | true | Must be "postgres". | | host | string | true | IP address to connect to (e.g. "127.0.0.1") | | port | string | true | Port to connect to (e.g. "5432") | | database | string | true | Name of the Postgres database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/redis.md b/docs/en/resources/sources/redis.md index c0dee699e0b0..51c8cfde00e2 100644 --- a/docs/en/resources/sources/redis.md +++ b/docs/en/resources/sources/redis.md @@ -34,16 +34,16 @@ connections must authenticate in order to connect. Specify your AUTH string in the password field: ```yaml -sources: - my-redis-instance: - kind: redis - address: - - 127.0.0.1:6379 - username: ${MY_USER_NAME} - password: ${MY_AUTH_STRING} # Omit this field if you don't have a password. - # database: 0 - # clusterEnabled: false - # useGCPIAM: false +kind: sources +name: my-redis-instance +type: redis +address: + - 127.0.0.1:6379 +username: ${MY_USER_NAME} +password: ${MY_AUTH_STRING} # Omit this field if you don't have a password. +# database: 0 +# clusterEnabled: false +# useGCPIAM: false ``` {{< notice tip >}} @@ -59,14 +59,14 @@ string. Here is an example tools.yaml config with [AUTH][auth] enabled: ```yaml -sources: - my-redis-cluster-instance: - kind: memorystore-redis - address: - - 127.0.0.1:6379 - password: ${MY_AUTH_STRING} - # useGCPIAM: false - # clusterEnabled: false +kind: sources +name: my-redis-cluster-instance +type: memorystore-redis +address: + - 127.0.0.1:6379 +password: ${MY_AUTH_STRING} +# useGCPIAM: false +# clusterEnabled: false ``` Memorystore Redis Cluster supports IAM authentication instead. Grant your @@ -76,13 +76,13 @@ Here is an example tools.yaml config for Memorystore Redis Cluster instances using IAM authentication: ```yaml -sources: - my-redis-cluster-instance: - kind: memorystore-redis - address: - - 127.0.0.1:6379 - useGCPIAM: true - clusterEnabled: true +kind: sources +name: my-redis-cluster-instance +type: memorystore-redis +address: + - 127.0.0.1:6379 +useGCPIAM: true +clusterEnabled: true ``` [iam]: https://cloud.google.com/memorystore/docs/cluster/about-iam-auth @@ -91,7 +91,7 @@ sources: | **field** | **type** | **required** | **description** | |----------------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "memorystore-redis". | +| type | string | true | Must be "memorystore-redis". | | address | string | true | Primary endpoint for the Memorystore Redis instance to connect to. | | username | string | false | If you are using a non-default user, specify the user name here. If you are using Memorystore for Redis, leave this field blank | | password | string | false | If you have [Redis AUTH][auth] enabled, specify the AUTH string here | diff --git a/docs/en/resources/sources/serverless-spark.md b/docs/en/resources/sources/serverless-spark.md index 1f2afc3cec75..f08c6c5e79dc 100644 --- a/docs/en/resources/sources/serverless-spark.md +++ b/docs/en/resources/sources/serverless-spark.md @@ -49,17 +49,17 @@ set up your ADC. ## Example ```yaml -sources: - my-serverless-spark-source: - kind: serverless-spark - project: my-project-id - location: us-central1 +kind: sources +name: my-serverless-spark-source +type: serverless-spark +project: my-project-id +location: us-central1 ``` ## Reference | **field** | **type** | **required** | **description** | | --------- | :------: | :----------: | ----------------------------------------------------------------- | -| kind | string | true | Must be "serverless-spark". | +| type | string | true | Must be "serverless-spark". | | project | string | true | ID of the GCP project with Serverless for Apache Spark resources. | | location | string | true | Location containing Serverless for Apache Spark resources. | diff --git a/docs/en/resources/sources/singlestore.md b/docs/en/resources/sources/singlestore.md index fef332a7d88a..9acde19ff0e9 100644 --- a/docs/en/resources/sources/singlestore.md +++ b/docs/en/resources/sources/singlestore.md @@ -39,15 +39,15 @@ database user][singlestore-user] to login to the database with. ## Example ```yaml -sources: - my-singlestore-source: - kind: singlestore - host: 127.0.0.1 - port: 3306 - database: my_db - user: ${USER_NAME} - password: ${PASSWORD} - queryTimeout: 30s # Optional: query timeout duration +kind: sources +name: my-singlestore-source +type: singlestore +host: 127.0.0.1 +port: 3306 +database: my_db +user: ${USER_NAME} +password: ${PASSWORD} +queryTimeout: 30s # Optional: query timeout duration ``` {{< notice tip >}} @@ -59,7 +59,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |--------------|:--------:|:------------:|-------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "singlestore". | +| type | string | true | Must be "singlestore". | | host | string | true | IP address to connect to (e.g. "127.0.0.1"). | | port | string | true | Port to connect to (e.g. "3306"). | | database | string | true | Name of the SingleStore database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/snowflake.md b/docs/en/resources/sources/snowflake.md index 5981538ec5d3..3a048470e7a9 100644 --- a/docs/en/resources/sources/snowflake.md +++ b/docs/en/resources/sources/snowflake.md @@ -31,16 +31,16 @@ Snowflake user to login to the database with. ## Example ```yaml -sources: - my-sf-source: - kind: snowflake - account: ${SNOWFLAKE_ACCOUNT} - user: ${SNOWFLAKE_USER} - password: ${SNOWFLAKE_PASSWORD} - database: ${SNOWFLAKE_DATABASE} - schema: ${SNOWFLAKE_SCHEMA} - warehouse: ${SNOWFLAKE_WAREHOUSE} - role: ${SNOWFLAKE_ROLE} +kind: sources +name: my-sf-source +type: snowflake +account: ${SNOWFLAKE_ACCOUNT} +user: ${SNOWFLAKE_USER} +password: ${SNOWFLAKE_PASSWORD} +database: ${SNOWFLAKE_DATABASE} +schema: ${SNOWFLAKE_SCHEMA} +warehouse: ${SNOWFLAKE_WAREHOUSE} +role: ${SNOWFLAKE_ROLE} ``` {{< notice tip >}} @@ -52,7 +52,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|------------------------------------------------------------------------| -| kind | string | true | Must be "snowflake". | +| type | string | true | Must be "snowflake". | | account | string | true | Your Snowflake account identifier. | | user | string | true | Name of the Snowflake user to connect as (e.g. "my-sf-user"). | | password | string | true | Password of the Snowflake user (e.g. "my-password"). | diff --git a/docs/en/resources/sources/spanner.md b/docs/en/resources/sources/spanner.md index 373ba75446a3..c8039583ac77 100644 --- a/docs/en/resources/sources/spanner.md +++ b/docs/en/resources/sources/spanner.md @@ -64,20 +64,20 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -sources: - my-spanner-source: - kind: "spanner" - project: "my-project-id" - instance: "my-instance" - database: "my_db" - # dialect: "googlesql" +kind: sources +name: my-spanner-source +type: "spanner" +project: "my-project-id" +instance: "my-instance" +database: "my_db" +# dialect: "googlesql" ``` ## Reference | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "spanner". | +| type | string | true | Must be "spanner". | | project | string | true | Id of the GCP project that the cluster was created in (e.g. "my-project-id"). | | instance | string | true | Name of the Spanner instance. | | database | string | true | Name of the database on the Spanner instance | diff --git a/docs/en/resources/sources/sqlite.md b/docs/en/resources/sources/sqlite.md index 5a3c6df91806..aae3030347fa 100644 --- a/docs/en/resources/sources/sqlite.md +++ b/docs/en/resources/sources/sqlite.md @@ -48,19 +48,19 @@ You need a SQLite database file. This can be: ## Example ```yaml -sources: - my-sqlite-db: - kind: "sqlite" - database: "/path/to/database.db" +kind: sources +name: my-sqlite-db +type: "sqlite" +database: "/path/to/database.db" ``` For an in-memory database: ```yaml -sources: - my-sqlite-memory-db: - kind: "sqlite" - database: ":memory:" +kind: sources +name: my-sqlite-memory-db +type: "sqlite" +database: ":memory:" ``` ## Reference @@ -69,7 +69,7 @@ sources: | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|---------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "sqlite". | +| type | string | true | Must be "sqlite". | | database | string | true | Path to SQLite database file, or ":memory:" for an in-memory database. | ### Connection Properties diff --git a/docs/en/resources/sources/tidb.md b/docs/en/resources/sources/tidb.md index 3b22db0bdb02..2bb4b62c6634 100644 --- a/docs/en/resources/sources/tidb.md +++ b/docs/en/resources/sources/tidb.md @@ -46,29 +46,29 @@ console. - TiDB Cloud ```yaml - sources: - my-tidb-cloud-source: - kind: tidb - host: gateway01.us-west-2.prod.aws.tidbcloud.com - port: 4000 - database: my_db - user: ${TIDB_USERNAME} - password: ${TIDB_PASSWORD} - # SSL is automatically enabled for TiDB Cloud + kind: sources + name: my-tidb-cloud-source + type: tidb + host: gateway01.us-west-2.prod.aws.tidbcloud.com + port: 4000 + database: my_db + user: ${TIDB_USERNAME} + password: ${TIDB_PASSWORD} + # SSL is automatically enabled for TiDB Cloud ``` - Self-Hosted TiDB ```yaml - sources: - my-tidb-source: - kind: tidb - host: 127.0.0.1 - port: 4000 - database: my_db - user: ${TIDB_USERNAME} - password: ${TIDB_PASSWORD} - # ssl: true # Optional: enable SSL for secure connections + kind: sources + name: my-tidb-source + type: tidb + host: 127.0.0.1 + port: 4000 + database: my_db + user: ${TIDB_USERNAME} + password: ${TIDB_PASSWORD} + # ssl: true # Optional: enable SSL for secure connections ``` {{< notice tip >}} @@ -80,7 +80,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | |-----------|:--------:|:------------:|--------------------------------------------------------------------------------------------| -| kind | string | true | Must be "tidb". | +| type | string | true | Must be "tidb". | | host | string | true | IP address or hostname to connect to (e.g. "127.0.0.1" or "gateway01.*.tidbcloud.com"). | | port | string | true | Port to connect to (typically "4000" for TiDB). | | database | string | true | Name of the TiDB database to connect to (e.g. "my_db"). | diff --git a/docs/en/resources/sources/trino.md b/docs/en/resources/sources/trino.md index e6a91226819d..d3ae1e6fcf1f 100644 --- a/docs/en/resources/sources/trino.md +++ b/docs/en/resources/sources/trino.md @@ -32,15 +32,15 @@ the catalogs and schemas you want to query. ## Example ```yaml -sources: - my-trino-source: - kind: trino - host: trino.example.com - port: "8080" - user: ${TRINO_USER} # Optional for anonymous access - password: ${TRINO_PASSWORD} # Optional - catalog: hive - schema: default +kind: sources +name: my-trino-source +type: trino +host: trino.example.com +port: "8080" +user: ${TRINO_USER} # Optional for anonymous access +password: ${TRINO_PASSWORD} # Optional +catalog: hive +schema: default ``` {{< notice tip >}} @@ -52,7 +52,7 @@ instead of hardcoding your secrets into the configuration file. | **field** | **type** | **required** | **description** | | ---------------------- | :------: | :----------: | ---------------------------------------------------------------------------- | -| kind | string | true | Must be "trino". | +| type | string | true | Must be "trino". | | host | string | true | Trino coordinator hostname (e.g. "trino.example.com") | | port | string | true | Trino coordinator port (e.g. "8080", "8443") | | user | string | false | Username for authentication (e.g. "analyst"). Optional for anonymous access. | diff --git a/docs/en/resources/sources/valkey.md b/docs/en/resources/sources/valkey.md index 8b1e68e94758..aedb8759aaf6 100644 --- a/docs/en/resources/sources/valkey.md +++ b/docs/en/resources/sources/valkey.md @@ -27,16 +27,16 @@ the [official Valkey website](https://valkey.io/topics/quickstart/). ## Example ```yaml -sources: - my-valkey-instance: - kind: valkey - address: - - 127.0.0.1:6379 - username: ${YOUR_USERNAME} - password: ${YOUR_PASSWORD} - # database: 0 - # useGCPIAM: false - # disableCache: false +kind: sources +name: my-valkey-instance +type: valkey +address: + - 127.0.0.1:6379 +username: ${YOUR_USERNAME} +password: ${YOUR_PASSWORD} +# database: 0 +# useGCPIAM: false +# disableCache: false ``` {{< notice tip >}} @@ -51,12 +51,12 @@ authentication. Grant your account the required [IAM role][iam] and set `useGCPIAM` to `true`: ```yaml -sources: - my-valkey-instance: - kind: valkey - address: - - 127.0.0.1:6379 - useGCPIAM: true +kind: sources +name: my-valkey-instance +type: valkey +address: + - 127.0.0.1:6379 +useGCPIAM: true ``` [iam]: https://cloud.google.com/memorystore/docs/valkey/about-iam-auth @@ -65,7 +65,7 @@ sources: | **field** | **type** | **required** | **description** | |--------------|:--------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "valkey". | +| type | string | true | Must be "valkey". | | address | []string | true | Endpoints for the Valkey instance to connect to. | | username | string | false | If you are using a non-default user, specify the user name here. If you are using Memorystore for Valkey, leave this field blank | | password | string | false | Password for the Valkey instance | diff --git a/docs/en/resources/sources/yugabytedb.md b/docs/en/resources/sources/yugabytedb.md index cdd13621977d..b923327cdcc1 100644 --- a/docs/en/resources/sources/yugabytedb.md +++ b/docs/en/resources/sources/yugabytedb.md @@ -17,23 +17,23 @@ compatibility. ## Example ```yaml -sources: - my-yb-source: - kind: yugabytedb - host: 127.0.0.1 - port: 5433 - database: yugabyte - user: ${USER_NAME} - password: ${PASSWORD} - loadBalance: true - topologyKeys: cloud.region.zone1:1,cloud.region.zone2:2 +kind: sources +name: my-yb-source +type: yugabytedb +host: 127.0.0.1 +port: 5433 +database: yugabyte +user: ${USER_NAME} +password: ${PASSWORD} +loadBalance: true +topologyKeys: cloud.region.zone1:1,cloud.region.zone2:2 ``` ## Reference | **field** | **type** | **required** | **description** | |------------------------------|:--------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "yugabytedb". | +| type | string | true | Must be "yugabytedb". | | host | string | true | IP address to connect to. | | port | integer | true | Port to connect to. The default port is 5433. | | database | string | true | Name of the YugabyteDB database to connect to. The default database name is yugabyte. | diff --git a/docs/en/resources/tools/_index.md b/docs/en/resources/tools/_index.md index 43a72427f77a..aaf8f73f7480 100644 --- a/docs/en/resources/tools/_index.md +++ b/docs/en/resources/tools/_index.md @@ -12,41 +12,41 @@ statement. You can define Tools as a map in the `tools` section of your `tools.yaml` file. Typically, a tool will require a source to act on: ```yaml -tools: - search_flights_by_number: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT * FROM flights - WHERE airline = $1 - AND flight_number = $2 - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - An airline code is a code for an airline service consisting of a two-character - airline designator and followed by a flight number, which is a 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closest to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: postgres-sql +source: my-pg-instance +statement: | + SELECT * FROM flights + WHERE airline = $1 + AND flight_number = $2 + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + An airline code is a code for an airline service consisting of a two-character + airline designator and followed by a flight number, which is a 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closest to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ## Specifying Parameters @@ -55,13 +55,13 @@ Parameters for each Tool will define what inputs the agent will need to provide to invoke them. Parameters should be pass as a list of Parameter objects: ```yaml - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Basic Parameters @@ -71,10 +71,10 @@ most cases, the description will be provided to the LLM as context on specifying the parameter. ```yaml - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier ``` | **field** | **type** | **required** | **description** | @@ -97,16 +97,16 @@ To use the `array` type, you must also specify what kind of items are in the list using the items field: ```yaml - parameters: - - name: preferred_airlines - type: array - description: A list of airline, ordered by preference. - items: - name: name - type: string - description: Name of the airline. - statement: | - SELECT * FROM airlines WHERE preferred_airlines = ANY($1); +parameters: + - name: preferred_airlines + type: array + description: A list of airline, ordered by preference. + items: + name: name + type: string + description: Name of the airline. +statement: | + SELECT * FROM airlines WHERE preferred_airlines = ANY($1); ``` | **field** | **type** | **required** | **description** | @@ -141,10 +141,10 @@ This is the default behavior when valueType is omitted. It's useful for passing a flexible group of settings. ```yaml - parameters: - - name: execution_context - type: map - description: A flexible set of key-value pairs for the execution environment. +parameters: + - name: execution_context + type: map + description: A flexible set of key-value pairs for the execution environment. ``` #### Typed Map @@ -153,11 +153,11 @@ Specify valueType to ensure all values in the map are of the same type. An error will be thrown in case of value type mismatch. ```yaml - parameters: - - name: user_scores - type: map - description: A map of user IDs to their scores. All scores must be integers. - valueType: integer # This enforces the value type for all entries. +parameters: + - name: user_scores + type: map + description: A map of user IDs to their scores. All scores must be integers. + valueType: integer # This enforces the value type for all entries. ``` ### Authenticated Parameters @@ -171,21 +171,21 @@ the required [authServices](../authServices/) to specific claims within the user's ID token. ```yaml - tools: - search_flights_by_user_id: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT * FROM flights WHERE user_id = $1 - parameters: - - name: user_id - type: string - description: Auto-populated from Google login - authServices: - # Refer to one of the `authServices` defined - - name: my-google-auth - # `sub` is the OIDC claim field for user ID - field: sub +kind: tools +name: search_flights_by_user_id +type: postgres-sql +source: my-pg-instance +statement: | + SELECT * FROM flights WHERE user_id = $1 +parameters: + - name: user_id + type: string + description: Auto-populated from Google login + authServices: + # Refer to one of the `authServices` defined + - name: my-google-auth + # `sub` is the OIDC claim field for user ID + field: sub ``` | **field** | **type** | **required** | **description** | @@ -222,31 +222,31 @@ can use `minValue` and `maxValue` to define the allowable range. {{< /notice >}} ```yaml -tools: - select_columns_from_table: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT {{array .columnNames}} FROM {{.tableName}} - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - "columnNames": ["id", "name"] - }} - templateParameters: - - name: tableName - type: string - description: Table to select from - - name: columnNames - type: array - description: The columns to select - items: - name: column - type: string - description: Name of a column to select - escape: double-quotes # with this, the statement will resolve to `SELECT "id", "name" FROM flights` +kind: tools +name: select_columns_from_table +type: postgres-sql +source: my-pg-instance +statement: | + SELECT {{array .columnNames}} FROM {{.tableName}} +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + "columnNames": ["id", "name"] + }} +templateParameters: + - name: tableName + type: string + description: Table to select from + - name: columnNames + type: array + description: The columns to select + items: + name: column + type: string + description: Name of a column to select + escape: double-quotes # with this, the statement will resolve to `SELECT "id", "name" FROM flights` ``` | **field** | **type** | **required** | **description** | @@ -267,16 +267,16 @@ specifying an `authRequired` field. Specify a list of [authServices](../authServices/) defined in the previous section. ```yaml -tools: - search_all_flight: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT * FROM flights - # A list of `authServices` defined previously - authRequired: - - my-google-auth - - other-auth-service +kind: tools +name: search_all_flight +type: postgres-sql +source: my-pg-instance +statement: | + SELECT * FROM flights +# A list of `authServices` defined previously +authRequired: + - my-google-auth + - other-auth-service ``` ## Kinds of tools diff --git a/docs/en/resources/tools/alloydb/alloydb-create-cluster.md b/docs/en/resources/tools/alloydb/alloydb-create-cluster.md index b70d320213f6..621feb18520d 100644 --- a/docs/en/resources/tools/alloydb/alloydb-create-cluster.md +++ b/docs/en/resources/tools/alloydb/alloydb-create-cluster.md @@ -40,17 +40,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - create_cluster: - kind: alloydb-create-cluster - source: alloydb-admin-source - description: Use this tool to create a new AlloyDB cluster in a given project and location. +kind: tools +name: create_cluster +type: alloydb-create-cluster +source: alloydb-admin-source +description: Use this tool to create a new AlloyDB cluster in a given project and location. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be alloydb-create-cluster. | +| type | string | true | Must be alloydb-create-cluster. | | source | string | true | The name of an `alloydb-admin` source. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/alloydb/alloydb-create-instance.md b/docs/en/resources/tools/alloydb/alloydb-create-instance.md index 6a8680af9477..19f6aaa95c56 100644 --- a/docs/en/resources/tools/alloydb/alloydb-create-instance.md +++ b/docs/en/resources/tools/alloydb/alloydb-create-instance.md @@ -45,17 +45,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - create_instance: - kind: alloydb-create-instance - source: alloydb-admin-source - description: Use this tool to create a new AlloyDB instance within a specified cluster. +kind: tools +name: create_instance +type: alloydb-create-instance +source: alloydb-admin-source +description: Use this tool to create a new AlloyDB instance within a specified cluster. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-create-instance. | +| type | string | true | Must be alloydb-create-instance. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-create-user.md b/docs/en/resources/tools/alloydb/alloydb-create-user.md index b4ca9bcbb35b..3c7e4507816f 100644 --- a/docs/en/resources/tools/alloydb/alloydb-create-user.md +++ b/docs/en/resources/tools/alloydb/alloydb-create-user.md @@ -39,17 +39,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - create_user: - kind: alloydb-create-user - source: alloydb-admin-source - description: Use this tool to create a new database user for an AlloyDB cluster. +kind: tools +name: create_user +type: alloydb-create-user +source: alloydb-admin-source +description: Use this tool to create a new database user for an AlloyDB cluster. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-create-user. | +| type | string | true | Must be alloydb-create-user. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-get-cluster.md b/docs/en/resources/tools/alloydb/alloydb-get-cluster.md index 29f5af0cf56d..fcd5049393d5 100644 --- a/docs/en/resources/tools/alloydb/alloydb-get-cluster.md +++ b/docs/en/resources/tools/alloydb/alloydb-get-cluster.md @@ -3,7 +3,7 @@ title: alloydb-get-cluster type: docs weight: 1 description: "The \"alloydb-get-cluster\" tool retrieves details for a specific AlloyDB cluster.\n" -aliases: [/resources/tools/alloydb-get-cluster] +alias: [/resources/tools/alloydb-get-cluster] --- ## About @@ -21,17 +21,17 @@ specified AlloyDB cluster. It is compatible with ## Example ```yaml -tools: - get_specific_cluster: - kind: alloydb-get-cluster - source: my-alloydb-admin-source - description: Use this tool to retrieve details for a specific AlloyDB cluster. +kind: tools +name: get_specific_cluster +type: alloydb-get-cluster +source: my-alloydb-admin-source +description: Use this tool to retrieve details for a specific AlloyDB cluster. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-get-cluster. | +| type | string | true | Must be alloydb-get-cluster. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-get-instance.md b/docs/en/resources/tools/alloydb/alloydb-get-instance.md index 0305c4bcc0d3..65a9a7ec8136 100644 --- a/docs/en/resources/tools/alloydb/alloydb-get-instance.md +++ b/docs/en/resources/tools/alloydb/alloydb-get-instance.md @@ -22,17 +22,17 @@ specified AlloyDB instance. It is compatible with ## Example ```yaml -tools: - get_specific_instance: - kind: alloydb-get-instance - source: my-alloydb-admin-source - description: Use this tool to retrieve details for a specific AlloyDB instance. +kind: tools +name: get_specific_instance +type: alloydb-get-instance +source: my-alloydb-admin-source +description: Use this tool to retrieve details for a specific AlloyDB instance. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be alloydb-get-instance. | +| type | string | true | Must be alloydb-get-instance. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-get-user.md b/docs/en/resources/tools/alloydb/alloydb-get-user.md index afee54aab5c1..a223afe8f717 100644 --- a/docs/en/resources/tools/alloydb/alloydb-get-user.md +++ b/docs/en/resources/tools/alloydb/alloydb-get-user.md @@ -22,17 +22,17 @@ specified AlloyDB user. It is compatible with ## Example ```yaml -tools: - get_specific_user: - kind: alloydb-get-user - source: my-alloydb-admin-source - description: Use this tool to retrieve details for a specific AlloyDB user. +kind: tools +name: get_specific_user +type: alloydb-get-user +source: my-alloydb-admin-source +description: Use this tool to retrieve details for a specific AlloyDB user. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-get-user. | +| type | string | true | Must be alloydb-get-user. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-list-clusters.md b/docs/en/resources/tools/alloydb/alloydb-list-clusters.md index 6f0beb3a6785..644f98729b11 100644 --- a/docs/en/resources/tools/alloydb/alloydb-list-clusters.md +++ b/docs/en/resources/tools/alloydb/alloydb-list-clusters.md @@ -24,17 +24,17 @@ location. The tool takes the following input parameters: ## Example ```yaml -tools: - list_clusters: - kind: alloydb-list-clusters - source: alloydb-admin-source - description: Use this tool to list all AlloyDB clusters in a given project and location. +kind: tools +name: list_clusters +type: alloydb-list-clusters +source: alloydb-admin-source +description: Use this tool to list all AlloyDB clusters in a given project and location. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-list-clusters. | +| type | string | true | Must be alloydb-list-clusters. | | source | string | true | The name of an `alloydb-admin` source. | -| description | string | false | Description of the tool that is passed to the agent. | +| description | string | false | Description of the tool that is passed to the agent. | \ No newline at end of file diff --git a/docs/en/resources/tools/alloydb/alloydb-list-instances.md b/docs/en/resources/tools/alloydb/alloydb-list-instances.md index ecf1f9a8ddf8..fdf0c35c9dc5 100644 --- a/docs/en/resources/tools/alloydb/alloydb-list-instances.md +++ b/docs/en/resources/tools/alloydb/alloydb-list-instances.md @@ -26,17 +26,17 @@ parameters: ## Example ```yaml -tools: - list_instances: - kind: alloydb-list-instances - source: alloydb-admin-source - description: Use this tool to list all AlloyDB instances for a given project, cluster and location. +kind: tools +name: list_instances +type: alloydb-list-instances +source: alloydb-admin-source +description: Use this tool to list all AlloyDB instances for a given project, cluster and location. ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-list-instances. | +| type | string | true | Must be alloydb-list-instances. | | source | string | true | The name of an `alloydb-admin` source. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/alloydb/alloydb-list-users.md b/docs/en/resources/tools/alloydb/alloydb-list-users.md index 73d3015b88e0..b735cd06079e 100644 --- a/docs/en/resources/tools/alloydb/alloydb-list-users.md +++ b/docs/en/resources/tools/alloydb/alloydb-list-users.md @@ -22,17 +22,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - list_users: - kind: alloydb-list-users - source: alloydb-admin-source - description: Use this tool to list all database users within an AlloyDB cluster +kind: tools +name: list_users +type: alloydb-list-users +source: alloydb-admin-source +description: Use this tool to list all database users within an AlloyDB cluster ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------- | -| kind | string | true | Must be alloydb-list-users. | +| type | string | true | Must be alloydb-list-users. | | source | string | true | The name of an `alloydb-admin` source. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/alloydb/alloydb-wait-for-operation.md b/docs/en/resources/tools/alloydb/alloydb-wait-for-operation.md index f5e84e5b973b..98d67e90847a 100644 --- a/docs/en/resources/tools/alloydb/alloydb-wait-for-operation.md +++ b/docs/en/resources/tools/alloydb/alloydb-wait-for-operation.md @@ -25,22 +25,22 @@ and shouldn't be used for production agents. ## Example ```yaml -tools: - wait_for_operation: - kind: alloydb-wait-for-operation - source: my-alloydb-admin-source - description: "This will poll on operations API until the operation is done. For checking operation status we need projectId, locationID and operationId. Once instance is created give follow up steps on how to use the variables to bring data plane MCP server up in local and remote setup." - delay: 1s - maxDelay: 4m - multiplier: 2 - maxRetries: 10 +kind: tools +name: wait_for_operation +type: alloydb-wait-for-operation +source: my-alloydb-admin-source +description: "This will poll on operations API until the operation is done. For checking operation status we need projectId, locationID and operationId. Once instance is created give follow up steps on how to use the variables to bring data plane MCP server up in local and remote setup." +delay: 1s +maxDelay: 4m +multiplier: 2 +maxRetries: 10 ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "alloydb-wait-for-operation". | +| type | string | true | Must be "alloydb-wait-for-operation". | | source | string | true | The name of a `alloydb-admin` source to use for authentication. | | description | string | false | A description of the tool. | | delay | duration | false | The initial delay between polling requests (e.g., `3s`). Defaults to 3 seconds. | diff --git a/docs/en/resources/tools/alloydbainl/alloydb-ai-nl.md b/docs/en/resources/tools/alloydbainl/alloydb-ai-nl.md index aa6d377f2c97..97364c5dd81f 100644 --- a/docs/en/resources/tools/alloydbainl/alloydb-ai-nl.md +++ b/docs/en/resources/tools/alloydbainl/alloydb-ai-nl.md @@ -103,29 +103,29 @@ CREATE EXTENSION IF NOT EXISTS parameterized_views; ## Example ```yaml -tools: - ask_questions: - kind: alloydb-ai-nl - source: my-alloydb-source - description: "Ask questions to check information about flights" - nlConfig: "cymbal_air_nl_config" - nlConfigParameters: - - name: user_email - type: string - description: User ID of the logged in user. - # note: we strongly recommend using features like Authenticated or - # Bound parameters to prevent the LLM from seeing these params and - # specifying values it shouldn't in the tool input - authServices: - - name: my_google_service - field: email +kind: tools +name: ask_questions +type: alloydb-ai-nl +source: my-alloydb-source +description: "Ask questions to check information about flights" +nlConfig: "cymbal_air_nl_config" +nlConfigParameters: + - name: user_email + type: string + description: User ID of the logged in user. + # note: we strongly recommend using features like Authenticated or + # Bound parameters to prevent the LLM from seeing these params and + # specifying values it shouldn't in the tool input + authServices: + - name: my_google_service + field: email ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:---------------------------------------:|:------------:|--------------------------------------------------------------------------| -| kind | string | true | Must be "alloydb-ai-nl". | +| type | string | true | Must be "alloydb-ai-nl". | | source | string | true | Name of the AlloyDB source the natural language query should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | nlConfig | string | true | The name of the `nl_config` in AlloyDB | diff --git a/docs/en/resources/tools/bigquery/bigquery-analyze-contribution.md b/docs/en/resources/tools/bigquery/bigquery-analyze-contribution.md index 3561af3dd318..ed126246a4a2 100644 --- a/docs/en/resources/tools/bigquery/bigquery-analyze-contribution.md +++ b/docs/en/resources/tools/bigquery/bigquery-analyze-contribution.md @@ -64,11 +64,11 @@ the `bigquery` source: ## Example ```yaml -tools: - contribution_analyzer: - kind: bigquery-analyze-contribution - source: my-bigquery-source - description: Use this tool to run contribution analysis on a dataset in BigQuery. +kind: tools +name: contribution_analyzer +type: bigquery-analyze-contribution +source: my-bigquery-source +description: Use this tool to run contribution analysis on a dataset in BigQuery. ``` ## Sample Prompt @@ -88,6 +88,6 @@ And use the following sample prompts to call this tool: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "bigquery-analyze-contribution". | +| type | string | true | Must be "bigquery-analyze-contribution". | | source | string | true | Name of the source the tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-conversational-analytics.md b/docs/en/resources/tools/bigquery/bigquery-conversational-analytics.md index 2c8ef2908349..486db6083e4b 100644 --- a/docs/en/resources/tools/bigquery/bigquery-conversational-analytics.md +++ b/docs/en/resources/tools/bigquery/bigquery-conversational-analytics.md @@ -53,19 +53,19 @@ dataset specified in the `table_references` parameter. ## Example ```yaml -tools: - ask_data_insights: - kind: bigquery-conversational-analytics - source: my-bigquery-source - description: | - Use this tool to perform data analysis, get insights, or answer complex - questions about the contents of specific BigQuery tables. +kind: tools +name: ask_data_insights +type: bigquery-conversational-analytics +source: my-bigquery-source +description: | + Use this tool to perform data analysis, get insights, or answer complex + questions about the contents of specific BigQuery tables. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "bigquery-conversational-analytics". | +| type | string | true | Must be "bigquery-conversational-analytics". | | source | string | true | Name of the source for chat. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-execute-sql.md b/docs/en/resources/tools/bigquery/bigquery-execute-sql.md index b59ae5824971..783ba5c7421f 100644 --- a/docs/en/resources/tools/bigquery/bigquery-execute-sql.md +++ b/docs/en/resources/tools/bigquery/bigquery-execute-sql.md @@ -54,17 +54,17 @@ layer of security by controlling which datasets can be accessed: ## Example ```yaml -tools: - execute_sql_tool: - kind: bigquery-execute-sql - source: my-bigquery-source - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: bigquery-execute-sql +source: my-bigquery-source +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "bigquery-execute-sql". | +| type | string | true | Must be "bigquery-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-forecast.md b/docs/en/resources/tools/bigquery/bigquery-forecast.md index 823eb487e1ce..188a7d11c7de 100644 --- a/docs/en/resources/tools/bigquery/bigquery-forecast.md +++ b/docs/en/resources/tools/bigquery/bigquery-forecast.md @@ -58,11 +58,11 @@ the `bigquery` source: ## Example ```yaml -tools: - forecast_tool: - kind: bigquery-forecast - source: my-bigquery-source - description: Use this tool to forecast time series data in BigQuery. +kind: tools +name: forecast_tool +type: bigquery-forecast +source: my-bigquery-source +description: Use this tool to forecast time series data in BigQuery. ``` ## Sample Prompt @@ -78,6 +78,6 @@ You can use the following sample prompts to call this tool: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|---------------------------------------------------------| -| kind | string | true | Must be "bigquery-forecast". | +| type | string | true | Must be "bigquery-forecast". | | source | string | true | Name of the source the forecast tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-get-dataset-info.md b/docs/en/resources/tools/bigquery/bigquery-get-dataset-info.md index 460816d290a0..e68fe835749d 100644 --- a/docs/en/resources/tools/bigquery/bigquery-get-dataset-info.md +++ b/docs/en/resources/tools/bigquery/bigquery-get-dataset-info.md @@ -34,17 +34,17 @@ The tool's behavior regarding these parameters is influenced by the ## Example ```yaml -tools: - bigquery_get_dataset_info: - kind: bigquery-get-dataset-info - source: my-bigquery-source - description: Use this tool to get dataset metadata. +kind: tools +name: bigquery_get_dataset_info +type: bigquery-get-dataset-info +source: my-bigquery-source +description: Use this tool to get dataset metadata. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-get-dataset-info". | +| type | string | true | Must be "bigquery-get-dataset-info". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-get-table-info.md b/docs/en/resources/tools/bigquery/bigquery-get-table-info.md index e05f74c13184..807e9a8f04fb 100644 --- a/docs/en/resources/tools/bigquery/bigquery-get-table-info.md +++ b/docs/en/resources/tools/bigquery/bigquery-get-table-info.md @@ -35,17 +35,17 @@ The tool's behavior regarding these parameters is influenced by the ## Example ```yaml -tools: - bigquery_get_table_info: - kind: bigquery-get-table-info - source: my-bigquery-source - description: Use this tool to get table metadata. +kind: tools +name: bigquery_get_table_info +type: bigquery-get-table-info +source: my-bigquery-source +description: Use this tool to get table metadata. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-get-table-info". | +| type | string | true | Must be "bigquery-get-table-info". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-list-dataset-ids.md b/docs/en/resources/tools/bigquery/bigquery-list-dataset-ids.md index 176ad78dfefd..c2cd8b760927 100644 --- a/docs/en/resources/tools/bigquery/bigquery-list-dataset-ids.md +++ b/docs/en/resources/tools/bigquery/bigquery-list-dataset-ids.md @@ -32,17 +32,17 @@ The tool's behavior regarding this parameter is influenced by the ## Example ```yaml -tools: - bigquery_list_dataset_ids: - kind: bigquery-list-dataset-ids - source: my-bigquery-source - description: Use this tool to get dataset metadata. +kind: tools +name: bigquery_list_dataset_ids +type: bigquery-list-dataset-ids +source: my-bigquery-source +description: Use this tool to get dataset metadata. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-list-dataset-ids". | +| type | string | true | Must be "bigquery-list-dataset-ids". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-list-table-ids.md b/docs/en/resources/tools/bigquery/bigquery-list-table-ids.md index 5e72d0b22ae0..828e84cb8fe9 100644 --- a/docs/en/resources/tools/bigquery/bigquery-list-table-ids.md +++ b/docs/en/resources/tools/bigquery/bigquery-list-table-ids.md @@ -34,17 +34,17 @@ will be used as the default value for the `dataset` parameter. ## Example ```yaml -tools: - bigquery_list_table_ids: - kind: bigquery-list-table-ids - source: my-bigquery-source - description: Use this tool to get table metadata. +kind: tools +name: bigquery_list_table_ids +type: bigquery-list-table-ids +source: my-bigquery-source +description: Use this tool to get table metadata. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-list-table-ids". | +| type | string | true | Must be "bigquery-list-table-ids". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-search-catalog.md b/docs/en/resources/tools/bigquery/bigquery-search-catalog.md index 32a107983ed5..3994e4744a3b 100644 --- a/docs/en/resources/tools/bigquery/bigquery-search-catalog.md +++ b/docs/en/resources/tools/bigquery/bigquery-search-catalog.md @@ -48,17 +48,17 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -tools: - search_catalog: - kind: bigquery-search-catalog - source: bigquery-source - description: Use this tool to find tables, views, models, routines or connections. +kind: tools +name: search_catalog +type: bigquery-search-catalog +source: bigquery-source +description: Use this tool to find tables, views, models, routines or connections. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-search-catalog". | +| type | string | true | Must be "bigquery-search-catalog". | | source | string | true | Name of the source the tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/bigquery/bigquery-sql.md b/docs/en/resources/tools/bigquery/bigquery-sql.md index c07192f71089..39d5c750ffd7 100644 --- a/docs/en/resources/tools/bigquery/bigquery-sql.md +++ b/docs/en/resources/tools/bigquery/bigquery-sql.md @@ -46,36 +46,36 @@ same query. > identifiers, column names, table names, or other parts of the query. ```yaml -tools: - # Example: Querying a user table in BigQuery - search_users_bq: - kind: bigquery-sql - source: my-bigquery-source - statement: | - SELECT - id, - name, - email - FROM - `my-project.my-dataset.users` - WHERE - id = @id OR email = @email; - description: | - Use this tool to get information for a specific user. - Takes an id number or a name and returns info on the user. - - Example: - {{ - "id": 123, - "name": "Alice", - }} - parameters: - - name: id - type: integer - description: User ID - - name: email - type: string - description: Email address of the user +# Example: Querying a user table in BigQuery +kind: tools +name: search_users_bq +type: bigquery-sql +source: my-bigquery-source +statement: | + SELECT + id, + name, + email + FROM + `my-project.my-dataset.users` + WHERE + id = @id OR email = @email; +description: | + Use this tool to get information for a specific user. + Takes an id number or a name and returns info on the user. + + Example: + {{ + "id": 123, + "name": "Alice", + }} +parameters: + - name: id + type: integer + description: User ID + - name: email + type: string + description: Email address of the user ``` ### Example with Template Parameters @@ -87,31 +87,31 @@ tools: > [templateParameters](../#template-parameters). ```yaml -tools: - list_table: - kind: bigquery-sql - source: my-bigquery-source - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: bigquery-sql +source: my-bigquery-source +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:---------------------------------------------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigquery-sql". | +| type | string | true | Must be "bigquery-sql". | | source | string | true | Name of the source the GoogleSQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | The GoogleSQL statement to execute. | | parameters | [parameters](../#specifying-parameters) | false | List of [parameters](../#specifying-parameters) that will be inserted into the SQL statement. | -| templateParameters | [templateParameters](../#template-parameters) | false | List of [templateParameters](../#template-parameters) that will be inserted into the SQL statement before executing prepared statement. | +| templateParameters | [templateParameters](../#template-parameters) | false | List of [templateParameters](../#template-parameters) that will be inserted into the SQL statement before executing prepared statement. | \ No newline at end of file diff --git a/docs/en/resources/tools/bigtable/bigtable-sql.md b/docs/en/resources/tools/bigtable/bigtable-sql.md index cce122f94d88..7d56be05b573 100644 --- a/docs/en/resources/tools/bigtable/bigtable-sql.md +++ b/docs/en/resources/tools/bigtable/bigtable-sql.md @@ -40,35 +40,35 @@ inserted according to their name: e.g. `@name`. > names, or other parts of the query. ```yaml -tools: - search_user_by_id_or_name: - kind: bigtable-sql - source: my-bigtable-instance - statement: | - SELECT - TO_INT64(cf[ 'id' ]) as id, - CAST(cf[ 'name' ] AS string) as name, - FROM - mytable - WHERE - TO_INT64(cf[ 'id' ]) = @id - OR CAST(cf[ 'name' ] AS string) = @name; - description: | - Use this tool to get information for a specific user. - Takes an id number or a name and returns info on the user. - - Example: - {{ - "id": 123, - "name": "Alice", - }} - parameters: - - name: id - type: integer - description: User ID - - name: name - type: string - description: Name of the user +kind: tools +name: search_user_by_id_or_name +type: bigtable-sql +source: my-bigtable-instance +statement: | + SELECT + TO_INT64(cf[ 'id' ]) as id, + CAST(cf[ 'name' ] AS string) as name, + FROM + mytable + WHERE + TO_INT64(cf[ 'id' ]) = @id + OR CAST(cf[ 'name' ] AS string) = @name; +description: | + Use this tool to get information for a specific user. + Takes an id number or a name and returns info on the user. + + Example: + {{ + "id": 123, + "name": "Alice", + }} +parameters: + - name: id + type: integer + description: User ID + - name: name + type: string + description: Name of the user ``` ### Example with Template Parameters @@ -80,29 +80,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: bigtable-sql - source: my-bigtable-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: bigtable-sql +source: my-bigtable-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "bigtable-sql". | +| type | string | true | Must be "bigtable-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/cassandra/cassandra-cql.md b/docs/en/resources/tools/cassandra/cassandra-cql.md index feb092ee2199..14f1eb8e01e7 100644 --- a/docs/en/resources/tools/cassandra/cassandra-cql.md +++ b/docs/en/resources/tools/cassandra/cassandra-cql.md @@ -31,27 +31,27 @@ the form of placeholders `?`. > names, or other parts of the query. ```yaml -tools: - search_users_by_email: - kind: cassandra-cql - source: my-cassandra-cluster - statement: | - SELECT user_id, email, first_name, last_name, created_at - FROM users - WHERE email = ? - description: | - Use this tool to retrieve specific user information by their email address. - Takes an email address and returns user details including user ID, email, - first name, last name, and account creation timestamp. - Do NOT use this tool with a user ID or other identifiers. - Example: - {{ - "email": "user@example.com", - }} - parameters: - - name: email - type: string - description: User's email address +kind: tools +name: search_users_by_email +type: cassandra-cql +source: my-cassandra-cluster +statement: | + SELECT user_id, email, first_name, last_name, created_at + FROM users + WHERE email = ? +description: | + Use this tool to retrieve specific user information by their email address. + Takes an email address and returns user details including user ID, email, + first name, last name, and account creation timestamp. + Do NOT use this tool with a user ID or other identifiers. + Example: + {{ + "email": "user@example.com", + }} +parameters: + - name: email + type: string + description: User's email address ``` ### Example with Template Parameters @@ -63,33 +63,33 @@ tools: > [templateParameters](../#template-parameters). ```yaml -tools: - list_keyspace_table: - kind: cassandra-cql - source: my-cassandra-cluster - statement: | - SELECT * FROM {{.keyspace}}.{{.tableName}}; - description: | - Use this tool to list all information from a specific table in a keyspace. - Example: - {{ - "keyspace": "my_keyspace", - "tableName": "users", - }} - templateParameters: - - name: keyspace - type: string - description: Keyspace containing the table - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_keyspace_table +type: cassandra-cql +source: my-cassandra-cluster +statement: | + SELECT * FROM {{.keyspace}}.{{.tableName}}; +description: | + Use this tool to list all information from a specific table in a keyspace. + Example: + {{ + "keyspace": "my_keyspace", + "tableName": "users", + }} +templateParameters: + - name: keyspace + type: string + description: Keyspace containing the table + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:---------------------------------------------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "cassandra-cql". | +| type | string | true | Must be "cassandra-cql". | | source | string | true | Name of the source the CQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | CQL statement to execute. | diff --git a/docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md b/docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md index e197c1f05b8d..5e28b543864b 100644 --- a/docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md +++ b/docs/en/resources/tools/clickhouse/clickhouse-execute-sql.md @@ -25,11 +25,11 @@ capabilities for monitoring and debugging purposes. ## Example ```yaml -tools: - execute_sql_tool: - kind: clickhouse-execute-sql - source: my-clickhouse-instance - description: Use this tool to execute SQL statements against ClickHouse. +kind: tools +name: execute_sql_tool +type: clickhouse-execute-sql +source: my-clickhouse-instance +description: Use this tool to execute SQL statements against ClickHouse. ``` ## Parameters @@ -42,6 +42,6 @@ tools: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|-------------------------------------------------------| -| kind | string | true | Must be "clickhouse-execute-sql". | +| type | string | true | Must be "clickhouse-execute-sql". | | source | string | true | Name of the ClickHouse source to execute SQL against. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/clickhouse/clickhouse-list-databases.md b/docs/en/resources/tools/clickhouse/clickhouse-list-databases.md index 43e5f0e982f2..eedf197b410d 100644 --- a/docs/en/resources/tools/clickhouse/clickhouse-list-databases.md +++ b/docs/en/resources/tools/clickhouse/clickhouse-list-databases.md @@ -21,11 +21,11 @@ discovery and exploration tasks. ## Example ```yaml -tools: - list_clickhouse_databases: - kind: clickhouse-list-databases - source: my-clickhouse-instance - description: List all available databases in the ClickHouse instance +kind: tools +name: list_clickhouse_databases +type: clickhouse-list-databases +source: my-clickhouse-instance +description: List all available databases in the ClickHouse instance ``` ## Return Value @@ -49,7 +49,7 @@ Example response: | **field** | **type** | **required** | **description** | |--------------|:------------------:|:------------:|-------------------------------------------------------| -| kind | string | true | Must be "clickhouse-list-databases". | +| type | string | true | Must be "clickhouse-list-databases". | | source | string | true | Name of the ClickHouse source to list databases from. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | array of string | false | Authentication services required to use this tool. | diff --git a/docs/en/resources/tools/clickhouse/clickhouse-list-tables.md b/docs/en/resources/tools/clickhouse/clickhouse-list-tables.md index a886813e17c3..dbeb49c79c2a 100644 --- a/docs/en/resources/tools/clickhouse/clickhouse-list-tables.md +++ b/docs/en/resources/tools/clickhouse/clickhouse-list-tables.md @@ -21,11 +21,11 @@ user, making it useful for schema exploration and table discovery tasks. ## Example ```yaml -tools: - list_clickhouse_tables: - kind: clickhouse-list-tables - source: my-clickhouse-instance - description: List all tables in a specific ClickHouse database +kind: tools +name: list_clickhouse_tables +type: clickhouse-list-tables +source: my-clickhouse-instance +description: List all tables in a specific ClickHouse database ``` ## Parameters @@ -56,7 +56,7 @@ Example response: | **field** | **type** | **required** | **description** | |--------------|:------------------:|:------------:|---------------------------------------------------------| -| kind | string | true | Must be "clickhouse-list-tables". | +| type | string | true | Must be "clickhouse-list-tables". | | source | string | true | Name of the ClickHouse source to list tables from. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | array of string | false | Authentication services required to use this tool. | diff --git a/docs/en/resources/tools/clickhouse/clickhouse-sql.md b/docs/en/resources/tools/clickhouse/clickhouse-sql.md index 5d66d6826f14..b26bb6eadee6 100644 --- a/docs/en/resources/tools/clickhouse/clickhouse-sql.md +++ b/docs/en/resources/tools/clickhouse/clickhouse-sql.md @@ -21,60 +21,60 @@ query execution capabilities. ## Example ```yaml -tools: - my_analytics_query: - kind: clickhouse-sql - source: my-clickhouse-instance - description: Get user analytics for a specific date range - statement: | - SELECT - user_id, - count(*) as event_count, - max(timestamp) as last_event - FROM events - WHERE date >= ? AND date <= ? - GROUP BY user_id - ORDER BY event_count DESC - LIMIT ? - parameters: - - name: start_date - description: Start date for the query (YYYY-MM-DD format) - - name: end_date - description: End date for the query (YYYY-MM-DD format) - - name: limit - description: Maximum number of results to return +kind: tools +name: my_analytics_query +type: clickhouse-sql +source: my-clickhouse-instance +description: Get user analytics for a specific date range +statement: | + SELECT + user_id, + count(*) as event_count, + max(timestamp) as last_event + FROM events + WHERE date >= ? AND date <= ? + GROUP BY user_id + ORDER BY event_count DESC + LIMIT ? +parameters: + - name: start_date + description: Start date for the query (YYYY-MM-DD format) + - name: end_date + description: End date for the query (YYYY-MM-DD format) + - name: limit + description: Maximum number of results to return ``` ## Template Parameters Example ```yaml -tools: - flexible_table_query: - kind: clickhouse-sql - source: my-clickhouse-instance - description: Query any table with flexible columns - statement: | - SELECT {{columns}} - FROM {{table_name}} - WHERE created_date >= ? - LIMIT ? - templateParameters: - - name: columns - description: Comma-separated list of columns to select - - name: table_name - description: Name of the table to query - parameters: - - name: start_date - description: Start date filter - - name: limit - description: Maximum number of results +kind: tools +name: flexible_table_query +type: clickhouse-sql +source: my-clickhouse-instance +description: Query any table with flexible columns +statement: | + SELECT {{columns}} + FROM {{table_name}} + WHERE created_date >= ? + LIMIT ? +templateParameters: + - name: columns + description: Comma-separated list of columns to select + - name: table_name + description: Name of the table to query +parameters: + - name: start_date + description: Start date filter + - name: limit + description: Maximum number of results ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:------------------:|:------------:|-------------------------------------------------------| -| kind | string | true | Must be "clickhouse-sql". | +| type | string | true | Must be "clickhouse-sql". | | source | string | true | Name of the ClickHouse source to execute SQL against. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | The SQL statement template to execute. | diff --git a/docs/en/resources/tools/cloudgda/cloud-gda-query.md b/docs/en/resources/tools/cloudgda/cloud-gda-query.md index 39e5bf64ae04..d4163214247e 100644 --- a/docs/en/resources/tools/cloudgda/cloud-gda-query.md +++ b/docs/en/resources/tools/cloudgda/cloud-gda-query.md @@ -18,28 +18,28 @@ The `cloud-gemini-data-analytics-query` tool allows you to send natural language ## Example ```yaml -tools: - my-gda-query-tool: - kind: cloud-gemini-data-analytics-query - source: my-gda-source - description: "Use this tool to send natural language queries to the Gemini Data Analytics API and receive SQL, natural language answers, and explanations." - location: ${your_database_location} - context: - datasourceReferences: - cloudSqlReference: - databaseReference: - projectId: "${your_project_id}" - region: "${your_database_instance_region}" - instanceId: "${your_database_instance_id}" - databaseId: "${your_database_name}" - engine: "POSTGRESQL" - agentContextReference: - contextSetId: "${your_context_set_id}" # E.g. projects/${project_id}/locations/${context_set_location}/contextSets/${context_set_id} - generationOptions: - generateQueryResult: true - generateNaturalLanguageAnswer: true - generateExplanation: true - generateDisambiguationQuestion: true +kind: tools +name: my-gda-query-tool +type: cloud-gemini-data-analytics-query +source: my-gda-source +description: "Use this tool to send natural language queries to the Gemini Data Analytics API and receive SQL, natural language answers, and explanations." +location: ${your_database_location} +context: + datasourceReferences: + cloudSqlReference: + databaseReference: + projectId: "${your_project_id}" + region: "${your_database_instance_region}" + instanceId: "${your_database_instance_id}" + databaseId: "${your_database_name}" + engine: "POSTGRESQL" + agentContextReference: + contextSetId: "${your_context_set_id}" # E.g. projects/${project_id}/locations/${context_set_location}/contextSets/${context_set_id} +generationOptions: + generateQueryResult: true + generateNaturalLanguageAnswer: true + generateExplanation: true + generateDisambiguationQuestion: true ``` ### Usage Flow @@ -87,7 +87,7 @@ How many accounts who have region in Prague are eligible for loans? A3 contains | **field** | **type** | **required** | **description** | | ----------------- | :------: | :----------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| kind | string | true | Must be "cloud-gemini-data-analytics-query". | +| type | string | true | Must be "cloud-gemini-data-analytics-query". | | source | string | true | The name of the `cloud-gemini-data-analytics` source to use. | | description | string | true | A description of the tool's purpose. | | location | string | true | The Google Cloud location of the target database resource (e.g., "us-central1"). This is used to construct the parent resource name in the API call. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-fetch-page.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-fetch-page.md index 0e990c9feea6..f8cd93cef864 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-fetch-page.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-fetch-page.md @@ -23,18 +23,18 @@ response bundle. ## Example ```yaml -tools: - get_fhir_store: - kind: cloud-healthcare-fhir-fetch-page - source: my-healthcare-source - description: Use this tool to fetch a page of FHIR resources from a FHIR Bundle's entry.link.url +kind: tools +name: get_fhir_store +type: cloud-healthcare-fhir-fetch-page +source: my-healthcare-source +description: Use this tool to fetch a page of FHIR resources from a FHIR Bundle's entry.link.url ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-fhir-fetch-page". | +| type | string | true | Must be "cloud-healthcare-fhir-fetch-page". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-everything.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-everything.md index b66f65f4bc73..8f74aa139222 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-everything.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-everything.md @@ -22,18 +22,18 @@ types, or only resources that have been updated after a given time. ## Example ```yaml -tools: - fhir_patient_everything: - kind: cloud-healthcare-fhir-patient-everything - source: my-healthcare-source - description: Use this tool to retrieve all the information about a given patient. +kind: tools +name: fhir_patient_everything +type: cloud-healthcare-fhir-patient-everything +source: my-healthcare-source +description: Use this tool to retrieve all the information about a given patient. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|-----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-fhir-patient-everything". | +| type | string | true | Must be "cloud-healthcare-fhir-patient-everything". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-search.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-search.md index 73155c90e1d2..f3cdab733b0f 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-search.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-fhir-patient-search.md @@ -21,18 +21,18 @@ given criteria. ## Example ```yaml -tools: - fhir_patient_search: - kind: cloud-healthcare-fhir-patient-search - source: my-healthcare-source - description: Use this tool to search for patients in the FHIR store. +kind: tools +name: fhir_patient_search +type: cloud-healthcare-fhir-patient-search +source: my-healthcare-source +description: Use this tool to search for patients in the FHIR store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-fhir-patient-search". | +| type | string | true | Must be "cloud-healthcare-fhir-patient-search". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dataset.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dataset.md index 0bcdb6896d80..856e32725172 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dataset.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dataset.md @@ -21,17 +21,17 @@ configured in the source. It takes no extra parameters. ## Example ```yaml -tools: - get_dataset: - kind: cloud-healthcare-get-dataset - source: my-healthcare-source - description: Use this tool to get healthcare dataset metadata. +kind: tools +name: get_dataset +type: cloud-healthcare-get-dataset +source: my-healthcare-source +description: Use this tool to get healthcare dataset metadata. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-dataset". | +| type | string | true | Must be "cloud-healthcare-get-dataset". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store-metrics.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store-metrics.md index 8bd5d38b1fba..8f0b4f152b20 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store-metrics.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store-metrics.md @@ -20,18 +20,18 @@ store. It's compatible with the following sources: ## Example ```yaml -tools: - get_dicom_store_metrics: - kind: cloud-healthcare-get-dicom-store-metrics - source: my-healthcare-source - description: Use this tool to get metrics for a DICOM store. +kind: tools +name: get_dicom_store_metrics +type: cloud-healthcare-get-dicom-store-metrics +source: my-healthcare-source +description: Use this tool to get metrics for a DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|-----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-dicom-store-metrics". | +| type | string | true | Must be "cloud-healthcare-get-dicom-store-metrics". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store.md index 9828b06aea7d..ba44d9b2ccd8 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-dicom-store.md @@ -20,18 +20,18 @@ compatible with the following sources: ## Example ```yaml -tools: - get_dicom_store: - kind: cloud-healthcare-get-dicom-store - source: my-healthcare-source - description: Use this tool to get information about a DICOM store. +kind: tools +name: get_dicom_store +type: cloud-healthcare-get-dicom-store +source: my-healthcare-source +description: Use this tool to get information about a DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-dicom-store". | +| type | string | true | Must be "cloud-healthcare-get-dicom-store". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-resource.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-resource.md index ef093ec1a307..ab36abd08d3a 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-resource.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-resource.md @@ -23,18 +23,18 @@ by its type and ID. ## Example ```yaml -tools: - get_fhir_resource: - kind: cloud-healthcare-get-fhir-resource - source: my-healthcare-source - description: Use this tool to retrieve a specific FHIR resource. +kind: tools +name: get_fhir_resource +type: cloud-healthcare-get-fhir-resource +source: my-healthcare-source +description: Use this tool to retrieve a specific FHIR resource. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-fhir-resource". | +| type | string | true | Must be "cloud-healthcare-get-fhir-resource". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store-metrics.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store-metrics.md index e5209e6118ec..f53aafac4ed4 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store-metrics.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store-metrics.md @@ -20,18 +20,18 @@ compatible with the following sources: ## Example ```yaml -tools: - get_fhir_store_metrics: - kind: cloud-healthcare-get-fhir-store-metrics - source: my-healthcare-source - description: Use this tool to get metrics for a FHIR store. +kind: tools +name: get_fhir_store_metrics +type: cloud-healthcare-get-fhir-store-metrics +source: my-healthcare-source +description: Use this tool to get metrics for a FHIR store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-fhir-store-metrics". | +| type | string | true | Must be "cloud-healthcare-get-fhir-store-metrics". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store.md index a9ce8d4aee7b..ff08bf3b313a 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-get-fhir-store.md @@ -20,18 +20,18 @@ compatible with the following sources: ## Example ```yaml -tools: - get_fhir_store: - kind: cloud-healthcare-get-fhir-store - source: my-healthcare-source - description: Use this tool to get information about a FHIR store. +kind: tools +name: get_fhir_store +type: cloud-healthcare-get-fhir-store +source: my-healthcare-source +description: Use this tool to get information about a FHIR store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-get-fhir-store". | +| type | string | true | Must be "cloud-healthcare-get-fhir-store". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-dicom-stores.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-dicom-stores.md index 7a6b493aca9f..ce1238d63291 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-dicom-stores.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-dicom-stores.md @@ -22,17 +22,17 @@ stores in the dataset of the healthcare source. It takes no extra parameters. ## Example ```yaml -tools: - list_dicom_stores: - kind: cloud-healthcare-list-dicom-stores - source: my-healthcare-source - description: Use this tool to list DICOM stores in the healthcare dataset. +kind: tools +name: list_dicom_stores +type: cloud-healthcare-list-dicom-stores +source: my-healthcare-source +description: Use this tool to list DICOM stores in the healthcare dataset. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-list-dicom-stores". | +| type | string | true | Must be "cloud-healthcare-list-dicom-stores". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-fhir-stores.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-fhir-stores.md index ff10278203b9..12986af45dc8 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-fhir-stores.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-list-fhir-stores.md @@ -22,17 +22,17 @@ stores in the dataset of the healthcare source. It takes no extra parameters. ## Example ```yaml -tools: - list_fhir_stores: - kind: cloud-healthcare-list-fhir-stores - source: my-healthcare-source - description: Use this tool to list FHIR stores in the healthcare dataset. +kind: tools +name: list_fhir_stores +type: cloud-healthcare-list-fhir-stores +source: my-healthcare-source +description: Use this tool to list FHIR stores in the healthcare dataset. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-list-fhir-stores". | +| type | string | true | Must be "cloud-healthcare-list-fhir-stores". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-retrieve-rendered-dicom-instance.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-retrieve-rendered-dicom-instance.md index c1b99818efa6..1d8eea9f2966 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-retrieve-rendered-dicom-instance.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-retrieve-rendered-dicom-instance.md @@ -22,18 +22,18 @@ string of the image in JPEG format. ## Example ```yaml -tools: - retrieve_rendered_dicom_instance: - kind: cloud-healthcare-retrieve-rendered-dicom-instance - source: my-healthcare-source - description: Use this tool to retrieve a rendered DICOM instance from the DICOM store. +kind: tools +name: retrieve_rendered_dicom_instance +type: cloud-healthcare-retrieve-rendered-dicom-instance +source: my-healthcare-source +description: Use this tool to retrieve a rendered DICOM instance from the DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|--------------------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-retrieve-rendered-dicom-instance". | +| type | string | true | Must be "cloud-healthcare-retrieve-rendered-dicom-instance". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-instances.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-instances.md index 042253d91deb..554290fe37f6 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-instances.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-instances.md @@ -22,18 +22,18 @@ criteria. ## Example ```yaml -tools: - search_dicom_instances: - kind: cloud-healthcare-search-dicom-instances - source: my-healthcare-source - description: Use this tool to search for DICOM instances in the DICOM store. +kind: tools +name: search_dicom_instances +type: cloud-healthcare-search-dicom-instances +source: my-healthcare-source +description: Use this tool to search for DICOM instances in the DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-search-dicom-instances". | +| type | string | true | Must be "cloud-healthcare-search-dicom-instances". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-series.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-series.md index 1a8e76a18353..2dba31f3cf8f 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-series.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-series.md @@ -20,18 +20,18 @@ set of criteria. It's compatible with the following sources: ## Example ```yaml -tools: - search_dicom_series: - kind: cloud-healthcare-search-dicom-series - source: my-healthcare-source - description: Use this tool to search for DICOM series in the DICOM store. +kind: tools +name: search_dicom_series +type: cloud-healthcare-search-dicom-series +source: my-healthcare-source +description: Use this tool to search for DICOM series in the DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-search-dicom-series". | +| type | string | true | Must be "cloud-healthcare-search-dicom-series". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-studies.md b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-studies.md index 11d903629279..a3c8504444e7 100644 --- a/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-studies.md +++ b/docs/en/resources/tools/cloudhealthcare/cloud-healthcare-search-dicom-studies.md @@ -20,18 +20,18 @@ set of criteria. It's compatible with the following sources: ## Example ```yaml -tools: - search_dicom_studies: - kind: cloud-healthcare-search-dicom-studies - source: my-healthcare-source - description: Use this tool to search for DICOM studies in the DICOM store. +kind: tools +name: search_dicom_studies +type: cloud-healthcare-search-dicom-studies +source: my-healthcare-source +description: Use this tool to search for DICOM studies in the DICOM store. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "cloud-healthcare-search-dicom-studies". | +| type | string | true | Must be "cloud-healthcare-search-dicom-studies". | | source | string | true | Name of the healthcare source. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/cloudmonitoring/cloud-monitoring-query-prometheus.md b/docs/en/resources/tools/cloudmonitoring/cloud-monitoring-query-prometheus.md index 53ade0eb337c..8597c1dc1ae2 100644 --- a/docs/en/resources/tools/cloudmonitoring/cloud-monitoring-query-prometheus.md +++ b/docs/en/resources/tools/cloudmonitoring/cloud-monitoring-query-prometheus.md @@ -55,21 +55,21 @@ Here are some examples of how to use the `cloud-monitoring-query-prometheus` tool. ```yaml -tools: - get_wait_time_metrics: - kind: cloud-monitoring-query-prometheus - source: cloud-monitoring-source - description: | - This tool fetches system wait time information for AlloyDB cluster, instance. Get the `projectID`, `clusterID` and `instanceID` from the user intent. To use this tool, you must provide the Google Cloud `projectId` and a PromQL `query`. - Generate `query` using these metric details: - metric: `alloydb.googleapis.com/instance/postgresql/wait_time`, monitored_resource: `alloydb.googleapis.com/Instance`. labels: `cluster_id`, `instance_id`, `wait_event_type`, `wait_event_name`. - Basic time series example promql query: `avg_over_time({"__name__"="alloydb.googleapis.com/instance/postgresql/wait_time","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m])` +kind: tools +name: get_wait_time_metrics +type: cloud-monitoring-query-prometheus +source: cloud-monitoring-source +description: | + This tool fetches system wait time information for AlloyDB cluster, instance. Get the `projectID`, `clusterID` and `instanceID` from the user intent. To use this tool, you must provide the Google Cloud `projectId` and a PromQL `query`. + Generate `query` using these metric details: + metric: `alloydb.googleapis.com/instance/postgresql/wait_time`, monitored_resource: `alloydb.googleapis.com/Instance`. labels: `cluster_id`, `instance_id`, `wait_event_type`, `wait_event_name`. + Basic time series example promql query: `avg_over_time({"__name__"="alloydb.googleapis.com/instance/postgresql/wait_time","monitored_resource"="alloydb.googleapis.com/Instance","instance_id"="alloydb-instance"}[5m])` ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be cloud-monitoring-query-prometheus. | +| type | string | true | Must be cloud-monitoring-query-prometheus. | | source | string | true | The name of an `cloud-monitoring` source. | | description | string | true | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlcloneinstance.md b/docs/en/resources/tools/cloudsql/cloudsqlcloneinstance.md index 89fdb8d986c9..455381173dd4 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlcloneinstance.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlcloneinstance.md @@ -8,7 +8,7 @@ description: "Clone a Cloud SQL instance." The `cloud-sql-clone-instance` tool clones a Cloud SQL instance using the Cloud SQL Admin API. {{< notice info dd>}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Examples @@ -16,21 +16,21 @@ This tool uses a `source` of kind `cloud-sql-admin`. Basic clone (current state) ```yaml -tools: - clone-instance-basic: - kind: cloud-sql-clone-instance - source: cloud-sql-admin-source - description: "Creates an exact copy of a Cloud SQL instance. Supports configuring instance zones and high-availability setup through zone preferences." +kind: tools +name: clone-instance-basic +type: cloud-sql-clone-instance +source: cloud-sql-admin-source +description: "Creates an exact copy of a Cloud SQL instance. Supports configuring instance zones and high-availability setup through zone preferences." ``` Point-in-time recovery (PITR) clone ```yaml -tools: - clone-instance-pitr: - kind: cloud-sql-clone-instance - source: cloud-sql-admin-source - description: "Creates an exact copy of a Cloud SQL instance at a specific point in time (PITR). Supports configuring instance zones and high-availability setup through zone preferences" +kind: tools +name: clone-instance-pitr +type: cloud-sql-clone-instance +source: cloud-sql-admin-source +description: "Creates an exact copy of a Cloud SQL instance at a specific point in time (PITR). Supports configuring instance zones and high-availability setup through zone preferences" ``` ## Reference @@ -39,7 +39,7 @@ tools: | **field** | **type** | **required** | **description** | | -------------- | :------: | :----------: | ------------------------------------------------------------- | -| kind | string | true | Must be "cloud-sql-clone-instance". | +| type | string | true | Must be "cloud-sql-clone-instance". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlcreatebackup.md b/docs/en/resources/tools/cloudsql/cloudsqlcreatebackup.md index 751534a0ba3e..b76738964468 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlcreatebackup.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlcreatebackup.md @@ -8,7 +8,7 @@ description: "Creates a backup on a Cloud SQL instance." The `cloud-sql-create-backup` tool creates an on-demand backup on a Cloud SQL instance using the Cloud SQL Admin API. {{< notice info dd>}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Examples @@ -16,17 +16,17 @@ This tool uses a `source` of kind `cloud-sql-admin`. Basic backup creation (current state) ```yaml -tools: - backup-creation-basic: - kind: cloud-sql-create-backup - source: cloud-sql-admin-source - description: "Creates a backup on the given Cloud SQL instance." +kind: tools +name: backup-creation-basic +type: cloud-sql-create-backup +source: cloud-sql-admin-source +description: "Creates a backup on the given Cloud SQL instance." ``` ## Reference ### Tool Configuration | **field** | **type** | **required** | **description** | | -------------- | :------: | :----------: | ------------------------------------------------------------- | -| kind | string | true | Must be "cloud-sql-create-backup". | +| type | string | true | Must be "cloud-sql-create-backup". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlcreatedatabase.md b/docs/en/resources/tools/cloudsql/cloudsqlcreatedatabase.md index dbad4f33765a..96c41047d898 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlcreatedatabase.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlcreatedatabase.md @@ -10,24 +10,24 @@ The `cloud-sql-create-database` tool creates a new database in a specified Cloud SQL instance. {{< notice info >}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Example ```yaml -tools: - create-cloud-sql-database: - kind: cloud-sql-create-database - source: my-cloud-sql-admin-source - description: "Creates a new database in a Cloud SQL instance." +kind: tools +name: create-cloud-sql-database +type: cloud-sql-create-database +source: my-cloud-sql-admin-source +description: "Creates a new database in a Cloud SQL instance." ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ------------------------------------------------ | -| kind | string | true | Must be "cloud-sql-create-database". | +| type | string | true | Must be "cloud-sql-create-database". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlcreateusers.md b/docs/en/resources/tools/cloudsql/cloudsqlcreateusers.md index affee91cfc9e..243e812100c5 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlcreateusers.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlcreateusers.md @@ -10,23 +10,23 @@ The `cloud-sql-create-users` tool creates a new user in a specified Cloud SQL instance. It can create both built-in and IAM users. {{< notice info >}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Example ```yaml -tools: - create-cloud-sql-user: - kind: cloud-sql-create-users - source: my-cloud-sql-admin-source - description: "Creates a new user in a Cloud SQL instance. Both built-in and IAM users are supported. IAM users require an email account as the user name. IAM is the more secure and recommended way to manage users. The agent should always ask the user what type of user they want to create. For more information, see https://cloud.google.com/sql/docs/postgres/add-manage-iam-users" +kind: tools +name: create-cloud-sql-user +type: cloud-sql-create-users +source: my-cloud-sql-admin-source +description: "Creates a new user in a Cloud SQL instance. Both built-in and IAM users are supported. IAM users require an email account as the user name. IAM is the more secure and recommended way to manage users. The agent should always ask the user what type of user they want to create. For more information, see https://cloud.google.com/sql/docs/postgres/add-manage-iam-users" ``` ## Reference | **field** | **type** | **required** | **description** | | ------------ | :-------: | :----------: | ------------------------------------------------ | -| kind | string | true | Must be "cloud-sql-create-users". | +| type | string | true | Must be "cloud-sql-create-users". | | description | string | false | A description of the tool. | | source | string | true | The name of the `cloud-sql-admin` source to use. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlgetinstances.md b/docs/en/resources/tools/cloudsql/cloudsqlgetinstances.md index 711fc3b3335a..d6ab497995ed 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlgetinstances.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlgetinstances.md @@ -10,23 +10,23 @@ The `cloud-sql-get-instance` tool retrieves a Cloud SQL instance resource using the Cloud SQL Admin API. {{< notice info >}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Example ```yaml -tools: - get-sql-instance: - kind: cloud-sql-get-instance - source: my-cloud-sql-admin-source - description: "Gets a particular cloud sql instance." +kind: tools +name: get-sql-instance +type: cloud-sql-get-instance +source: my-cloud-sql-admin-source +description: "Gets a particular cloud sql instance." ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ------------------------------------------------ | -| kind | string | true | Must be "cloud-sql-get-instance". | +| type | string | true | Must be "cloud-sql-get-instance". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqllistdatabases.md b/docs/en/resources/tools/cloudsql/cloudsqllistdatabases.md index 54f8f3401dc8..2d86f5b23e1e 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqllistdatabases.md +++ b/docs/en/resources/tools/cloudsql/cloudsqllistdatabases.md @@ -18,15 +18,15 @@ Here is an example of how to configure the `cloud-sql-list-databases` tool in yo `tools.yaml` file: ```yaml -sources: - my-cloud-sql-admin-source: - kind: cloud-sql-admin - -tools: - list_my_databases: - kind: cloud-sql-list-databases - source: my-cloud-sql-admin-source - description: Use this tool to list all Cloud SQL databases in an instance. +kind: sources +name: my-cloud-sql-admin-source +type: cloud-sql-admin +--- +kind: tools +name: list_my_databases +type: cloud-sql-list-databases +source: my-cloud-sql-admin-source +description: Use this tool to list all Cloud SQL databases in an instance. ``` ## Parameters @@ -42,6 +42,6 @@ The `cloud-sql-list-databases` tool has two required parameters: | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | -------------------------------------------------------------- | -| kind | string | true | Must be "cloud-sql-list-databases". | +| type | string | true | Must be "cloud-sql-list-databases". | | source | string | true | The name of the `cloud-sql-admin` source to use for this tool. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqllistinstances.md b/docs/en/resources/tools/cloudsql/cloudsqllistinstances.md index 45e3c542e63b..c078aa43bd0d 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqllistinstances.md +++ b/docs/en/resources/tools/cloudsql/cloudsqllistinstances.md @@ -19,15 +19,15 @@ Here is an example of how to configure the `cloud-sql-list-instances` tool in your `tools.yaml` file: ```yaml -sources: - my-cloud-sql-admin-source: - kind: cloud-sql-admin - -tools: - list_my_instances: - kind: cloud-sql-list-instances - source: my-cloud-sql-admin-source - description: Use this tool to list all Cloud SQL instances in a project. +kind: sources +name: my-cloud-sql-admin-source +type: cloud-sql-admin +--- +kind: tools +name: list_my_instances +type: cloud-sql-list-instances +source: my-cloud-sql-admin-source +description: Use this tool to list all Cloud SQL instances in a project. ``` ## Parameters @@ -42,6 +42,6 @@ The `cloud-sql-list-instances` tool has one required parameter: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------------------| -| kind | string | true | Must be "cloud-sql-list-instances". | +| type | string | true | Must be "cloud-sql-list-instances". | | description | string | false | Description of the tool that is passed to the agent. | | source | string | true | The name of the `cloud-sql-admin` source to use for this tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlmssqlcreateinstance.md b/docs/en/resources/tools/cloudsql/cloudsqlmssqlcreateinstance.md index 6b7cd9beb998..20537242378b 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlmssqlcreateinstance.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlmssqlcreateinstance.md @@ -9,17 +9,17 @@ The `cloud-sql-mssql-create-instance` tool creates a Cloud SQL for SQL Server instance using the Cloud SQL Admin API. {{< notice info dd>}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Example ```yaml -tools: - create-sql-instance: - kind: cloud-sql-mssql-create-instance - source: cloud-sql-admin-source - description: "Creates a SQL Server instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 8 GiB RAM (`db-custom-2-8192`) configuration with Non-HA/zonal availability. For the `Production` template, it chooses a 4 vCPU, 26 GiB RAM (`db-custom-4-26624`) configuration with HA/regional availability. The Enterprise edition is used in both cases. The default database version is `SQLSERVER_2022_STANDARD`. The agent should ask the user if they want to use a different version." +kind: tools +name: create-sql-instance +type: cloud-sql-mssql-create-instance +source: cloud-sql-admin-source +description: "Creates a SQL Server instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 8 GiB RAM (`db-custom-2-8192`) configuration with Non-HA/zonal availability. For the `Production` template, it chooses a 4 vCPU, 26 GiB RAM (`db-custom-4-26624`) configuration with HA/regional availability. The Enterprise edition is used in both cases. The default database version is `SQLSERVER_2022_STANDARD`. The agent should ask the user if they want to use a different version." ``` ## Reference @@ -28,7 +28,7 @@ tools: | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ------------------------------------------------ | -| kind | string | true | Must be "cloud-sql-mssql-create-instance". | +| type | string | true | Must be "cloud-sql-mssql-create-instance". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlmysqlcreateinstance.md b/docs/en/resources/tools/cloudsql/cloudsqlmysqlcreateinstance.md index 8707b8fea244..d9e5a7dcee36 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlmysqlcreateinstance.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlmysqlcreateinstance.md @@ -18,15 +18,15 @@ Here is an example of how to configure the `cloud-sql-mysql-create-instance` tool in your `tools.yaml` file: ```yaml -sources: - my-cloud-sql-admin-source: - kind: cloud-sql-admin - -tools: - create_my_mysql_instance: - kind: cloud-sql-mysql-create-instance - source: my-cloud-sql-admin-source - description: "Creates a MySQL instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `MYSQL_8_4`. The agent should ask the user if they want to use a different version." +kind: sources +name: my-cloud-sql-admin-source +type: cloud-sql-admin +--- +kind: tools +name: create_my_mysql_instance +type: cloud-sql-mysql-create-instance +source: my-cloud-sql-admin-source +description: "Creates a MySQL instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `MYSQL_8_4`. The agent should ask the user if they want to use a different version." ``` ## Parameters @@ -45,6 +45,6 @@ The `cloud-sql-mysql-create-instance` tool has the following parameters: | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | -------------------------------------------------------------- | -| kind | string | true | Must be `cloud-sql-mysql-create-instance`. | +| type | string | true | Must be `cloud-sql-mysql-create-instance`. | | source | string | true | The name of the `cloud-sql-admin` source to use for this tool. | | description | string | false | A description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlpgcreateinstances.md b/docs/en/resources/tools/cloudsql/cloudsqlpgcreateinstances.md index b5675375924e..0d41a89e037d 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlpgcreateinstances.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlpgcreateinstances.md @@ -9,17 +9,17 @@ The `cloud-sql-postgres-create-instance` tool creates a Cloud SQL for PostgreSQL instance using the Cloud SQL Admin API. {{< notice info >}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Example ```yaml -tools: - create-sql-instance: - kind: cloud-sql-postgres-create-instance - source: cloud-sql-admin-source - description: "Creates a Postgres instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `POSTGRES_17`. The agent should ask the user if they want to use a different version." +kind: tools +name: create-sql-instance +type: cloud-sql-postgres-create-instance +source: cloud-sql-admin-source +description: "Creates a Postgres instance using `Production` and `Development` presets. For the `Development` template, it chooses a 2 vCPU, 16 GiB RAM, 100 GiB SSD configuration with Non-HA/zonal availability. For the `Production` template, it chooses an 8 vCPU, 64 GiB RAM, 250 GiB SSD configuration with HA/regional availability. The Enterprise Plus edition is used in both cases. The default database version is `POSTGRES_17`. The agent should ask the user if they want to use a different version." ``` ## Reference @@ -28,7 +28,7 @@ tools: | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ------------------------------------------------ | -| kind | string | true | Must be "cloud-sql-postgres-create-instance". | +| type | string | true | Must be "cloud-sql-postgres-create-instance". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlpgupgradeprecheck.md b/docs/en/resources/tools/cloudsql/cloudsqlpgupgradeprecheck.md index 4b5933a176f8..820bf440318e 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlpgupgradeprecheck.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlpgupgradeprecheck.md @@ -10,7 +10,7 @@ instance to assess its readiness for a major version upgrade using the Cloud SQL It helps identify potential incompatibilities or issues before starting the actual upgrade process. {{< notice info >}} -This tool uses a `source` of kind `cloud-sql-admin`. +This tool uses a `source` of type `cloud-sql-admin`. {{< /notice >}} ## Tool Inputs @@ -18,18 +18,18 @@ This tool uses a `source` of kind `cloud-sql-admin`. ### Example ```yaml -tools: - postgres-upgrade-precheck: - kind: postgres-upgrade-precheck - source: cloud-sql-admin-source - description: "Checks if a Cloud SQL PostgreSQL instance is ready for a major version upgrade to the specified target version." +kind: tools +name: postgres-upgrade-precheck +type: postgres-upgrade-precheck +source: cloud-sql-admin-source +description: "Checks if a Cloud SQL PostgreSQL instance is ready for a major version upgrade to the specified target version." ``` ### Reference | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | --------------------------------------------------------- | -| kind | string | true | Must be "postgres-upgrade-precheck". | +| type | string | true | Must be "postgres-upgrade-precheck". | | source | string | true | The name of the `cloud-sql-admin` source to use. | | description | string | false | A description of the tool. | diff --git a/docs/en/resources/tools/cloudsql/cloudsqlwaitforoperation.md b/docs/en/resources/tools/cloudsql/cloudsqlwaitforoperation.md index 3816d12bf39f..728d0e2bc8dc 100644 --- a/docs/en/resources/tools/cloudsql/cloudsqlwaitforoperation.md +++ b/docs/en/resources/tools/cloudsql/cloudsqlwaitforoperation.md @@ -14,22 +14,22 @@ exponential backoff. ## Example ```yaml -tools: - cloudsql-operations-get: - kind: cloud-sql-wait-for-operation - source: my-cloud-sql-source - description: "This will poll on operations API until the operation is done. For checking operation status we need projectId and operationId. Once instance is created give follow up steps on how to use the variables to bring data plane MCP server up in local and remote setup." - delay: 1s - maxDelay: 4m - multiplier: 2 - maxRetries: 10 +kind: tools +name: cloudsql-operations-get +type: cloud-sql-wait-for-operation +source: my-cloud-sql-source +description: "This will poll on operations API until the operation is done. For checking operation status we need projectId and operationId. Once instance is created give follow up steps on how to use the variables to bring data plane MCP server up in local and remote setup." +delay: 1s +maxDelay: 4m +multiplier: 2 +maxRetries: 10 ``` ## Reference | **field** | **type** | **required** | **description** | | ----------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "cloud-sql-wait-for-operation". | +| type | string | true | Must be "cloud-sql-wait-for-operation". | | source | string | true | The name of a `cloud-sql-admin` source to use for authentication. | | description | string | false | A description of the tool. | | delay | duration | false | The initial delay between polling requests (e.g., `3s`). Defaults to 3 seconds. | diff --git a/docs/en/resources/tools/couchbase/couchbase-sql.md b/docs/en/resources/tools/couchbase/couchbase-sql.md index 0f83f3cf5dcf..3932bf061305 100644 --- a/docs/en/resources/tools/couchbase/couchbase-sql.md +++ b/docs/en/resources/tools/couchbase/couchbase-sql.md @@ -27,37 +27,37 @@ parameters will be used according to their name: e.g. `$id`. > names, or other parts of the query. ```yaml -tools: - search_products_by_category: - kind: couchbase-sql - source: my-couchbase-instance - statement: | - SELECT p.name, p.price, p.description - FROM products p - WHERE p.category = $category AND p.price < $max_price - ORDER BY p.price DESC - LIMIT 10 - description: | - Use this tool to get a list of products for a specific category under a maximum price. - Takes a category name, e.g. "Electronics" and a maximum price e.g 500 and returns a list of product names, prices, and descriptions. - Do NOT use this tool with invalid category names. Do NOT guess a category name, Do NOT guess a price. - Example: - {{ - "category": "Electronics", - "max_price": 500 - }} - Example: - {{ - "category": "Furniture", - "max_price": 1000 - }} - parameters: - - name: category - type: string - description: Product category name - - name: max_price - type: integer - description: Maximum price (positive integer) +kind: tools +name: search_products_by_category +type: couchbase-sql +source: my-couchbase-instance +statement: | + SELECT p.name, p.price, p.description + FROM products p + WHERE p.category = $category AND p.price < $max_price + ORDER BY p.price DESC + LIMIT 10 +description: | + Use this tool to get a list of products for a specific category under a maximum price. + Takes a category name, e.g. "Electronics" and a maximum price e.g 500 and returns a list of product names, prices, and descriptions. + Do NOT use this tool with invalid category names. Do NOT guess a category name, Do NOT guess a price. + Example: + {{ + "category": "Electronics", + "max_price": 500 + }} + Example: + {{ + "category": "Furniture", + "max_price": 1000 + }} +parameters: + - name: category + type: string + description: Product category name + - name: max_price + type: integer + description: Maximum price (positive integer) ``` ### Example with Template Parameters @@ -69,29 +69,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: couchbase-sql - source: my-couchbase-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: couchbase-sql +source: my-couchbase-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "couchbase-sql". | +| type | string | true | Must be "couchbase-sql". | | source | string | true | Name of the source the SQL query should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute | diff --git a/docs/en/resources/tools/dataform/dataform-compile-local.md b/docs/en/resources/tools/dataform/dataform-compile-local.md index eb1127772e32..ba246562601f 100644 --- a/docs/en/resources/tools/dataform/dataform-compile-local.md +++ b/docs/en/resources/tools/dataform/dataform-compile-local.md @@ -44,15 +44,15 @@ for more details. ## Example ```yaml -tools: - my_dataform_compiler: - kind: dataform-compile-local - description: Use this tool to compile a local Dataform project. +kind: tools +name: my_dataform_compiler +type: dataform-compile-local +description: Use this tool to compile a local Dataform project. ``` ## Reference | **field** | **type** | **required** | **description** | |:------------|:---------|:-------------|:---------------------------------------------------| -| kind | string | true | Must be "dataform-compile-local". | +| type | string | true | Must be "dataform-compile-local". | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/dataplex/dataplex-lookup-entry.md b/docs/en/resources/tools/dataplex/dataplex-lookup-entry.md index ea19ed645140..669d47efc72f 100644 --- a/docs/en/resources/tools/dataplex/dataplex-lookup-entry.md +++ b/docs/en/resources/tools/dataplex/dataplex-lookup-entry.md @@ -56,17 +56,17 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -tools: - lookup_entry: - kind: dataplex-lookup-entry - source: my-dataplex-source - description: Use this tool to retrieve a specific entry in Dataplex Catalog. +kind: tools +name: lookup_entry +type: dataplex-lookup-entry +source: my-dataplex-source +description: Use this tool to retrieve a specific entry in Dataplex Catalog. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "dataplex-lookup-entry". | +| type | string | true | Must be "dataplex-lookup-entry". | | source | string | true | Name of the source the tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/dataplex/dataplex-search-aspect-types.md b/docs/en/resources/tools/dataplex/dataplex-search-aspect-types.md index 75d77939661b..1bb17579ba7d 100644 --- a/docs/en/resources/tools/dataplex/dataplex-search-aspect-types.md +++ b/docs/en/resources/tools/dataplex/dataplex-search-aspect-types.md @@ -49,17 +49,17 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -tools: - dataplex-search-aspect-types: - kind: dataplex-search-aspect-types - source: my-dataplex-source - description: Use this tool to find aspect types relevant to the query. +kind: tools +name: dataplex-search-aspect-types +type: dataplex-search-aspect-types +source: my-dataplex-source +description: Use this tool to find aspect types relevant to the query. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "dataplex-search-aspect-types". | +| type | string | true | Must be "dataplex-search-aspect-types". | | source | string | true | Name of the source the tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/dataplex/dataplex-search-entries.md b/docs/en/resources/tools/dataplex/dataplex-search-entries.md index 75099d64e8f3..b7c0bd3deb5d 100644 --- a/docs/en/resources/tools/dataplex/dataplex-search-entries.md +++ b/docs/en/resources/tools/dataplex/dataplex-search-entries.md @@ -49,17 +49,17 @@ applying IAM permissions and roles to an identity. ## Example ```yaml -tools: - dataplex-search-entries: - kind: dataplex-search-entries - source: my-dataplex-source - description: Use this tool to get all the entries based on the provided query. +kind: tools +name: dataplex-search-entries +type: dataplex-search-entries +source: my-dataplex-source +description: Use this tool to get all the entries based on the provided query. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "dataplex-search-entries". | +| type | string | true | Must be "dataplex-search-entries". | | source | string | true | Name of the source the tool should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/dgraph/dgraph-dql.md b/docs/en/resources/tools/dgraph/dgraph-dql.md index 3c8e7685f3a5..ba33a35a60f2 100644 --- a/docs/en/resources/tools/dgraph/dgraph-dql.md +++ b/docs/en/resources/tools/dgraph/dgraph-dql.md @@ -41,83 +41,83 @@ query. {{< tabpane persist="header" >}} {{< tab header="Query" lang="yaml" >}} -tools: - search_user: - kind: dgraph-dql - source: my-dgraph-source - statement: | - query all($role: string){ - users(func: has(name)) @filter(eq(role, $role) AND ge(age, 30) AND le(age, 50)) { - uid - name - email - role - age - } - } - isQuery: true - timeout: 20s - description: | - Use this tool to retrieve the details of users who are admins and are between 30 and 50 years old. - The query returns the user's name, email, role, and age. - This can be helpful when you want to fetch admin users within a specific age range. - Example: Fetch admins aged between 30 and 50: - [ - { - "name": "Alice", - "role": "admin", - "age": 35 - }, - { - "name": "Bob", - "role": "admin", - "age": 45 - } - ] - parameters: - - name: $role - type: string - description: admin +kind: tools +name: search_user +type: dgraph-dql +source: my-dgraph-source +statement: | + query all($role: string){ + users(func: has(name)) @filter(eq(role, $role) AND ge(age, 30) AND le(age, 50)) { + uid + name + email + role + age + } + } +isQuery: true +timeout: 20s +description: | + Use this tool to retrieve the details of users who are admins and are between 30 and 50 years old. + The query returns the user's name, email, role, and age. + This can be helpful when you want to fetch admin users within a specific age range. + Example: Fetch admins aged between 30 and 50: + [ + { + "name": "Alice", + "role": "admin", + "age": 35 + }, + { + "name": "Bob", + "role": "admin", + "age": 45 + } + ] +parameters: + - name: $role + type: string + description: admin {{< /tab >}} {{< tab header="Mutation" lang="yaml" >}} -tools: - dgraph-manage-user-instance: - kind: dgraph-dql - source: my-dgraph-source - isQuery: false - statement: | - { - set { - _:user1 $user1 . - _:user1 $email1 . - _:user1 "admin" . - _:user1 "35" . - - _:user2 $user2 . - _:user2 $email2 . - _:user2 "admin" . - _:user2 "45" . - } - } - description: | - Use this tool to insert or update user data into the Dgraph database. - The mutation adds or updates user details like name, email, role, and age. - Example: Add users Alice and Bob as admins with specific ages. - parameters: - - name: user1 - type: string - description: Alice - - name: email1 - type: string - description: alice@email.com - - name: user2 - type: string - description: Bob - - name: email2 - type: string - description: bob@email.com +kind: tools +name: dgraph-manage-user-instance +type: dgraph-dql +source: my-dgraph-source +isQuery: false +statement: | + { + set { + _:user1 $user1 . + _:user1 $email1 . + _:user1 "admin" . + _:user1 "35" . + + _:user2 $user2 . + _:user2 $email2 . + _:user2 "admin" . + _:user2 "45" . + } + } +description: | + Use this tool to insert or update user data into the Dgraph database. + The mutation adds or updates user details like name, email, role, and age. + Example: Add users Alice and Bob as admins with specific ages. +parameters: + - name: user1 + type: string + description: Alice + - name: email1 + type: string + description: alice@email.com + - name: user2 + type: string + description: Bob + - name: email2 + type: string + description: bob@email.com {{< /tab >}} {{< /tabpane >}} @@ -126,7 +126,7 @@ tools: | **field** | **type** | **required** | **description** | |-------------|:---------------------------------------:|:------------:|-------------------------------------------------------------------------------------------| -| kind | string | true | Must be "dgraph-dql". | +| type | string | true | Must be "dgraph-dql". | | source | string | true | Name of the source the dql query should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | dql statement to execute | diff --git a/docs/en/resources/tools/elasticsearch/elasticsearch-esql.md b/docs/en/resources/tools/elasticsearch/elasticsearch-esql.md index 2df0ef6e54ff..1e0f5c70c154 100644 --- a/docs/en/resources/tools/elasticsearch/elasticsearch-esql.md +++ b/docs/en/resources/tools/elasticsearch/elasticsearch-esql.md @@ -20,20 +20,20 @@ for more information. ## Example ```yaml -tools: - query_my_index: - kind: elasticsearch-esql - source: elasticsearch-source - description: Use this tool to execute ES|QL queries. - query: | - FROM my-index - | KEEP * - | LIMIT ?limit - parameters: - - name: limit - type: integer - description: Limit the number of results. - required: true +kind: tools +name: query_my_index +type: elasticsearch-esql +source: elasticsearch-source +description: Use this tool to execute ES|QL queries. +query: | + FROM my-index + | KEEP * + | LIMIT ?limit +parameters: + - name: limit + type: integer + description: Limit the number of results. + required: true ``` ## Parameters diff --git a/docs/en/resources/tools/firebird/firebird-execute-sql.md b/docs/en/resources/tools/firebird/firebird-execute-sql.md index fa75d04137e4..830037c3cf55 100644 --- a/docs/en/resources/tools/firebird/firebird-execute-sql.md +++ b/docs/en/resources/tools/firebird/firebird-execute-sql.md @@ -25,17 +25,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: firebird-execute-sql - source: my_firebird_db - description: Use this tool to execute a SQL statement against the Firebird database. +kind: tools +name: execute_sql_tool +type: firebird-execute-sql +source: my_firebird_db +description: Use this tool to execute a SQL statement against the Firebird database. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "firebird-execute-sql". | +| type | string | true | Must be "firebird-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/firebird/firebird-sql.md b/docs/en/resources/tools/firebird/firebird-sql.md index d07c3cb53a99..3e6614b9af24 100644 --- a/docs/en/resources/tools/firebird/firebird-sql.md +++ b/docs/en/resources/tools/firebird/firebird-sql.md @@ -32,68 +32,68 @@ prepared statement. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: firebird-sql - source: my_firebird_db - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: firebird-sql +source: my_firebird_db +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Named Parameters ```yaml -tools: - search_flights_by_airline: - kind: firebird-sql - source: my_firebird_db - statement: | - SELECT * FROM flights - WHERE airline = :airline - AND departure_date >= :start_date - AND departure_date <= :end_date - ORDER BY departure_date - description: | - Search for flights by airline within a date range using named parameters. - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: start_date - type: string - description: Start date in YYYY-MM-DD format - - name: end_date - type: string - description: End date in YYYY-MM-DD format +kind: tools +name: search_flights_by_airline +type: firebird-sql +source: my_firebird_db +statement: | + SELECT * FROM flights + WHERE airline = :airline + AND departure_date >= :start_date + AND departure_date <= :end_date + ORDER BY departure_date +description: | + Search for flights by airline within a date range using named parameters. +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: start_date + type: string + description: Start date in YYYY-MM-DD format + - name: end_date + type: string + description: End date in YYYY-MM-DD format ``` ### Example with Template Parameters @@ -105,29 +105,29 @@ tools: > [templateParameters](../#template-parameters). ```yaml -tools: - list_table: - kind: firebird-sql - source: my_firebird_db - statement: | - SELECT * FROM {{.tableName}} - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: firebird-sql +source: my_firebird_db +statement: | + SELECT * FROM {{.tableName}} +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:---------------------------------------------:|:------------:|-----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "firebird-sql". | +| type | string | true | Must be "firebird-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/firestore/firestore-add-documents.md b/docs/en/resources/tools/firestore/firestore-add-documents.md index 13f8b207eae6..b777be7f8d0e 100644 --- a/docs/en/resources/tools/firestore/firestore-add-documents.md +++ b/docs/en/resources/tools/firestore/firestore-add-documents.md @@ -59,11 +59,11 @@ must be wrapped with its type indicator: ### Basic Document Creation ```yaml -tools: - add-company-doc: - kind: firestore-add-documents - source: my-firestore - description: Add a new company document +kind: tools +name: add-company-doc +type: firestore-add-documents +source: my-firestore +description: Add a new company document ``` Usage: @@ -246,14 +246,14 @@ Usage: The tool can be configured to require authentication: ```yaml -tools: - secure-add-docs: - kind: firestore-add-documents - source: prod-firestore - description: Add documents with authentication required - authRequired: - - google-oauth - - api-key +kind: tools +name: secure-add-docs +type: firestore-add-documents +source: prod-firestore +description: Add documents with authentication required +authRequired: + - google-oauth + - api-key ``` ## Error Handling diff --git a/docs/en/resources/tools/firestore/firestore-delete-documents.md b/docs/en/resources/tools/firestore/firestore-delete-documents.md index 66343231d0bb..36d6b61fc38a 100644 --- a/docs/en/resources/tools/firestore/firestore-delete-documents.md +++ b/docs/en/resources/tools/firestore/firestore-delete-documents.md @@ -23,17 +23,17 @@ efficient batch deletion and returns the success status for each document. ## Example ```yaml -tools: - delete_user_documents: - kind: firestore-delete-documents - source: my-firestore-source - description: Use this tool to delete multiple documents from Firestore. +kind: tools +name: delete_user_documents +type: firestore-delete-documents +source: my-firestore-source +description: Use this tool to delete multiple documents from Firestore. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------------:|:------------:|----------------------------------------------------------| -| kind | string | true | Must be "firestore-delete-documents". | +| type | string | true | Must be "firestore-delete-documents". | | source | string | true | Name of the Firestore source to delete documents from. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/firestore/firestore-get-documents.md b/docs/en/resources/tools/firestore/firestore-get-documents.md index 0bc1bef1b856..a4a5b0df0c2c 100644 --- a/docs/en/resources/tools/firestore/firestore-get-documents.md +++ b/docs/en/resources/tools/firestore/firestore-get-documents.md @@ -23,17 +23,17 @@ such as existence status, creation time, update time, and read time. ## Example ```yaml -tools: - get_user_documents: - kind: firestore-get-documents - source: my-firestore-source - description: Use this tool to retrieve multiple documents from Firestore. +kind: tools +name: get_user_documents +type: firestore-get-documents +source: my-firestore-source +description: Use this tool to retrieve multiple documents from Firestore. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------------:|:------------:|------------------------------------------------------------| -| kind | string | true | Must be "firestore-get-documents". | +| type | string | true | Must be "firestore-get-documents". | | source | string | true | Name of the Firestore source to retrieve documents from. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/firestore/firestore-get-rules.md b/docs/en/resources/tools/firestore/firestore-get-rules.md index 568dc6b1da63..28b48e53abd2 100644 --- a/docs/en/resources/tools/firestore/firestore-get-rules.md +++ b/docs/en/resources/tools/firestore/firestore-get-rules.md @@ -23,17 +23,17 @@ content along with metadata such as the ruleset name, and timestamps. ## Example ```yaml -tools: - get_firestore_rules: - kind: firestore-get-rules - source: my-firestore-source - description: Use this tool to retrieve the active Firestore security rules. +kind: tools +name: get_firestore_rules +type: firestore-get-rules +source: my-firestore-source +description: Use this tool to retrieve the active Firestore security rules. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:-------------:|:------------:|-------------------------------------------------------| -| kind | string | true | Must be "firestore-get-rules". | +| type | string | true | Must be "firestore-get-rules". | | source | string | true | Name of the Firestore source to retrieve rules from. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/firestore/firestore-list-collections.md b/docs/en/resources/tools/firestore/firestore-list-collections.md index b2cc7ef6b611..971aed02b8c6 100644 --- a/docs/en/resources/tools/firestore/firestore-list-collections.md +++ b/docs/en/resources/tools/firestore/firestore-list-collections.md @@ -26,17 +26,17 @@ not provided, it lists all root-level collections in the database. ## Example ```yaml -tools: - list_firestore_collections: - kind: firestore-list-collections - source: my-firestore-source - description: Use this tool to list collections in Firestore. +kind: tools +name: list_firestore_collections +type: firestore-list-collections +source: my-firestore-source +description: Use this tool to list collections in Firestore. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:----------------:|:------------:|--------------------------------------------------------| -| kind | string | true | Must be "firestore-list-collections". | +| type | string | true | Must be "firestore-list-collections". | | source | string | true | Name of the Firestore source to list collections from. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/firestore/firestore-query-collection.md b/docs/en/resources/tools/firestore/firestore-query-collection.md index f615a9bc2ecd..774aa9f29e25 100644 --- a/docs/en/resources/tools/firestore/firestore-query-collection.md +++ b/docs/en/resources/tools/firestore/firestore-query-collection.md @@ -18,17 +18,17 @@ with filters, ordering, and limit capabilities. To use this tool, you need to configure it in your YAML configuration file: ```yaml -sources: - my-firestore: - kind: firestore - project: my-gcp-project - database: "(default)" - -tools: - query_collection: - kind: firestore-query-collection - source: my-firestore - description: Query Firestore collections with advanced filtering +kind: sources +name: my-firestore +type: firestore +project: my-gcp-project +database: "(default)" +--- +kind: tools +name: query_collection +type: firestore-query-collection +source: my-firestore +description: Query Firestore collections with advanced filtering ``` ## Parameters diff --git a/docs/en/resources/tools/firestore/firestore-query.md b/docs/en/resources/tools/firestore/firestore-query.md index 20fe9c8fd743..a3027e02d250 100644 --- a/docs/en/resources/tools/firestore/firestore-query.md +++ b/docs/en/resources/tools/firestore/firestore-query.md @@ -38,87 +38,87 @@ developers can use to create custom tools with specific query patterns. ### Basic Configuration ```yaml -tools: - query_countries: - kind: firestore-query - source: my-firestore-source - description: Query countries with dynamic filters - collectionPath: "countries" - filters: | - { - "field": "continent", - "op": "==", - "value": {"stringValue": "{{.continent}}"} - } - parameters: - - name: continent - type: string - description: Continent to filter by - required: true +kind: tools +name: query_countries +type: firestore-query +source: my-firestore-source +description: Query countries with dynamic filters +collectionPath: "countries" +filters: | + { + "field": "continent", + "op": "==", + "value": {"stringValue": "{{.continent}}"} + } +parameters: + - name: continent + type: string + description: Continent to filter by + required: true ``` ### Advanced Configuration with Complex Filters ```yaml -tools: - advanced_query: - kind: firestore-query - source: my-firestore-source - description: Advanced query with complex filters - collectionPath: "{{.collection}}" - filters: | +kind: tools +name: advanced_query +type: firestore-query +source: my-firestore-source +description: Advanced query with complex filters +collectionPath: "{{.collection}}" +filters: | + { + "or": [ + {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, { - "or": [ - {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, - { - "and": [ - {"field": "priority", "op": ">", "value": {"integerValue": "{{.priority}}"}}, - {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}}, - {"field": "active", "op": "==", "value": {"booleanValue": {{.isActive}}}} - ] - } + "and": [ + {"field": "priority", "op": ">", "value": {"integerValue": "{{.priority}}"}}, + {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}}, + {"field": "active", "op": "==", "value": {"booleanValue": {{.isActive}}}} ] } - select: - - name - - status - - priority - orderBy: - field: "{{.sortField}}" - direction: "{{.sortDirection}}" - limit: 100 - analyzeQuery: true - parameters: - - name: collection - type: string - description: Collection to query - required: true - - name: status - type: string - description: Status to filter by - required: true - - name: priority - type: string - description: Minimum priority value - required: true - - name: maxArea - type: float - description: Maximum area value - required: true - - name: isActive - type: boolean - description: Filter by active status - required: true - - name: sortField - type: string - description: Field to sort by - required: false - default: "createdAt" - - name: sortDirection - type: string - description: Sort direction (ASCENDING or DESCENDING) - required: false - default: "DESCENDING" + ] + } +select: + - name + - status + - priority +orderBy: + field: "{{.sortField}}" + direction: "{{.sortDirection}}" +limit: 100 +analyzeQuery: true +parameters: + - name: collection + type: string + description: Collection to query + required: true + - name: status + type: string + description: Status to filter by + required: true + - name: priority + type: string + description: Minimum priority value + required: true + - name: maxArea + type: float + description: Maximum area value + required: true + - name: isActive + type: boolean + description: Filter by active status + required: true + - name: sortField + type: string + description: Field to sort by + required: false + default: "createdAt" + - name: sortDirection + type: string + description: Sort direction (ASCENDING or DESCENDING) + required: false + default: "DESCENDING" ``` ## Parameters @@ -127,7 +127,7 @@ tools: | Parameter | Type | Required | Description | |------------------|---------|----------|-------------------------------------------------------------------------------------------------------------| -| `kind` | string | Yes | Must be `firestore-query` | +| `type` | string | Yes | Must be `firestore-query` | | `source` | string | Yes | Name of the Firestore source to use | | `description` | string | Yes | Description of what this tool does | | `collectionPath` | string | Yes | Path to the collection to query (supports templates) | @@ -254,103 +254,103 @@ The tool supports all Firestore native JSON value types: ### Example 1: Query with Dynamic Collection Path ```yaml -tools: - user_documents: - kind: firestore-query - source: my-firestore - description: Query user-specific documents - collectionPath: "users/{{.userId}}/documents" - filters: | - { - "field": "type", - "op": "==", - "value": {"stringValue": "{{.docType}}"} - } - parameters: - - name: userId - type: string - description: User ID - required: true - - name: docType - type: string - description: Document type to filter - required: true +kind: tools +name: user_documents +type: firestore-query +source: my-firestore +description: Query user-specific documents +collectionPath: "users/{{.userId}}/documents" +filters: | + { + "field": "type", + "op": "==", + "value": {"stringValue": "{{.docType}}"} + } +parameters: + - name: userId + type: string + description: User ID + required: true + - name: docType + type: string + description: Document type to filter + required: true ``` ### Example 2: Complex Geographic Query ```yaml -tools: - location_search: - kind: firestore-query - source: my-firestore - description: Search locations by area and population - collectionPath: "cities" - filters: | - { - "and": [ - {"field": "country", "op": "==", "value": {"stringValue": "{{.country}}"}}, - {"field": "population", "op": ">", "value": {"integerValue": "{{.minPopulation}}"}}, - {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}} - ] - } - orderBy: - field: "population" - direction: "DESCENDING" - limit: 50 - parameters: - - name: country - type: string - description: Country code - required: true - - name: minPopulation - type: string - description: Minimum population (as string for large numbers) - required: true - - name: maxArea - type: float - description: Maximum area in square kilometers - required: true +kind: tools +name: location_search +type: firestore-query +source: my-firestore +description: Search locations by area and population +collectionPath: "cities" +filters: | + { + "and": [ + {"field": "country", "op": "==", "value": {"stringValue": "{{.country}}"}}, + {"field": "population", "op": ">", "value": {"integerValue": "{{.minPopulation}}"}}, + {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}} + ] + } +orderBy: + field: "population" + direction: "DESCENDING" +limit: 50 +parameters: + - name: country + type: string + description: Country code + required: true + - name: minPopulation + type: string + description: Minimum population (as string for large numbers) + required: true + - name: maxArea + type: float + description: Maximum area in square kilometers + required: true ``` ### Example 3: Time-based Query with Analysis ```yaml -tools: - activity_log: - kind: firestore-query - source: my-firestore - description: Query activity logs within time range - collectionPath: "logs" - filters: | - { - "and": [ - {"field": "timestamp", "op": ">=", "value": {"timestampValue": "{{.startTime}}"}}, - {"field": "timestamp", "op": "<=", "value": {"timestampValue": "{{.endTime}}"}}, - {"field": "severity", "op": "in", "value": {"arrayValue": {"values": [ - {"stringValue": "ERROR"}, - {"stringValue": "CRITICAL"} - ]}}} - ] - } - select: - - timestamp - - message - - severity - - userId - orderBy: - field: "timestamp" - direction: "DESCENDING" - analyzeQuery: true - parameters: - - name: startTime - type: string - description: Start time in RFC3339 format - required: true - - name: endTime - type: string - description: End time in RFC3339 format - required: true +kind: tools +name: activity_log +type: firestore-query +source: my-firestore +description: Query activity logs within time range +collectionPath: "logs" +filters: | + { + "and": [ + {"field": "timestamp", "op": ">=", "value": {"timestampValue": "{{.startTime}}"}}, + {"field": "timestamp", "op": "<=", "value": {"timestampValue": "{{.endTime}}"}}, + {"field": "severity", "op": "in", "value": {"arrayValue": {"values": [ + {"stringValue": "ERROR"}, + {"stringValue": "CRITICAL"} + ]}}} + ] + } +select: + - timestamp + - message + - severity + - userId +orderBy: + field: "timestamp" + direction: "DESCENDING" +analyzeQuery: true +parameters: + - name: startTime + type: string + description: Start time in RFC3339 format + required: true + - name: endTime + type: string + description: End time in RFC3339 format + required: true ``` ## Usage diff --git a/docs/en/resources/tools/firestore/firestore-update-document.md b/docs/en/resources/tools/firestore/firestore-update-document.md index 56aad8d37101..0cbda2cbfa80 100644 --- a/docs/en/resources/tools/firestore/firestore-update-document.md +++ b/docs/en/resources/tools/firestore/firestore-update-document.md @@ -76,7 +76,7 @@ deleted. To delete a field, include it in the `updateMask` but omit it from | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "firestore-update-document". | +| type | string | true | Must be "firestore-update-document". | | source | string | true | Name of the Firestore source to update documents in. | | description | string | true | Description of the tool that is passed to the LLM. | @@ -85,11 +85,11 @@ deleted. To delete a field, include it in the `updateMask` but omit it from ### Basic Document Update (Full Merge) ```yaml -tools: - update-user-doc: - kind: firestore-update-document - source: my-firestore - description: Update a user document +kind: tools +name: update-user-doc +type: firestore-update-document +source: my-firestore +description: Update a user document ``` Usage: @@ -299,14 +299,14 @@ In this example: The tool can be configured to require authentication: ```yaml -tools: - secure-update-doc: - kind: firestore-update-document - source: prod-firestore - description: Update documents with authentication required - authRequired: - - google-oauth - - api-key +kind: tools +name: secure-update-doc +type: firestore-update-document +source: prod-firestore +description: Update documents with authentication required +authRequired: + - google-oauth + - api-key ``` ## Error Handling diff --git a/docs/en/resources/tools/firestore/firestore-validate-rules.md b/docs/en/resources/tools/firestore/firestore-validate-rules.md index 6f74bec52786..3e6b06952192 100644 --- a/docs/en/resources/tools/firestore/firestore-validate-rules.md +++ b/docs/en/resources/tools/firestore/firestore-validate-rules.md @@ -17,11 +17,11 @@ reporting with source positions and code snippets. ## Configuration ```yaml -tools: - firestore-validate-rules: - kind: firestore-validate-rules - source: - description: "Checks the provided Firestore Rules source for syntax and validation errors" +kind: tools +name: firestore-validate-rules +type: firestore-validate-rules +source: +description: "Checks the provided Firestore Rules source for syntax and validation errors" ``` ## Authentication diff --git a/docs/en/resources/tools/http/http.md b/docs/en/resources/tools/http/http.md index 466a86c36d73..19272c9035e2 100644 --- a/docs/en/resources/tools/http/http.md +++ b/docs/en/resources/tools/http/http.md @@ -31,36 +31,38 @@ For example, the following config allows you to reach different paths of the same server using multiple Tools: ```yaml -sources: - my-http-source: - kind: http - baseUrl: https://api.example.com - -tools: - my-post-tool: - kind: http - source: my-http-source - method: POST - path: /update - description: Tool to update information to the example API - - my-get-tool: - kind: http - source: my-http-source - method: GET - path: /search - description: Tool to search information from the example API - - my-dynamic-path-tool: - kind: http - source: my-http-source - method: GET - path: /{{.myPathParam}}/search - description: Tool to reach endpoint based on the input to `myPathParam` - pathParams: - - name: myPathParam - type: string - description: The dynamic path parameter +kind: sources +name: my-http-source +type: http +baseUrl: https://api.example.com +--- +kind: tools +name: my-post-tool +type: http +source: my-http-source +method: POST +path: /update +description: Tool to update information to the example API +--- +kind: tools +name: my-get-tool +type: http +source: my-http-source +method: GET +path: /search +description: Tool to search information from the example API +--- +kind: tools +name: my-dynamic-path-tool +type: http +source: my-http-source +method: GET +path: /{{.myPathParam}}/search +description: Tool to reach endpoint based on the input to `myPathParam` +pathParams: + - name: myPathParam + type: string + description: The dynamic path parameter ``` @@ -77,15 +79,16 @@ The HTTP Tool allows you to specify headers in two different ways: same for every invocation: ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search - description: Tool to search data from API - headers: - Authorization: API_KEY - Content-Type: application/json +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search +description: Tool to search data from API +headers: + Authorization: API_KEY + Content-Type: application/json ``` - Dynamic headers can be specified as parameters in the `headerParams` field. @@ -93,16 +96,17 @@ my-http-tool: is determined by the LLM input upon Tool invocation: ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search - description: some description - headerParams: - - name: Content-Type # Example LLM input: "application/json" - description: request content type - type: string +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search +description: some description +headerParams: + - name: Content-Type # Example LLM input: "application/json" + description: request content type + type: string ``` ### Query parameters @@ -115,28 +119,30 @@ filtering or sorting data. the URL itself: ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search?language=en&id=1 - description: Tool to search for item with ID 1 in English +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search?language=en&id=1 +description: Tool to search for item with ID 1 in English ``` - Dynamic request query parameters should be specified as parameters in the `queryParams` section: ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search - description: Tool to search for item with ID - queryParams: - - name: id - description: item ID - type: integer +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search +description: Tool to search for item with ID +queryParams: + - name: id + description: item ID + type: integer ``` ### Request body @@ -150,24 +156,25 @@ body payload upon Tool invocation. Example: ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search - description: Tool to search for person with name and age - requestBody: | - { - "age": {{.age}}, - "name": "{{.name}}" - } - bodyParams: - - name: age - description: age number - type: integer - - name: name - description: name string - type: string +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search +description: Tool to search for person with name and age +requestBody: | + { + "age": {{.age}}, + "name": "{{.name}}" + } +bodyParams: + - name: age + description: age number + type: integer + - name: name + description: name string + type: string ``` #### Formatting Parameters @@ -211,45 +218,46 @@ will send the following output: ## Example ```yaml -my-http-tool: - kind: http - source: my-http-source - method: GET - path: /search +kind: tools +name: my-http-tool +type: http +source: my-http-source +method: GET +path: /search +description: some description +authRequired: + - my-google-auth-service + - other-auth-service +queryParams: + - name: country description: some description - authRequired: - - my-google-auth-service - - other-auth-service - queryParams: - - name: country - description: some description - type: string - requestBody: | - { - "age": {{.age}}, - "city": "{{.city}}" - } - bodyParams: - - name: age - description: age number - type: integer - - name: city - description: city string - type: string - headers: - Authorization: API_KEY - Content-Type: application/json - headerParams: - - name: Language - description: language string - type: string + type: string +requestBody: | + { + "age": {{.age}}, + "city": "{{.city}}" + } +bodyParams: + - name: age + description: age number + type: integer + - name: city + description: city string + type: string +headers: + Authorization: API_KEY + Content-Type: application/json +headerParams: + - name: Language + description: language string + type: string ``` ## Reference | **field** | **type** | **required** | **description** | |--------------|:---------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "http". | +| type | string | true | Must be "http". | | source | string | true | Name of the source the HTTP request should be sent to. | | description | string | true | Description of the tool that is passed to the LLM. | | path | string | true | The path of the HTTP request. You can include static query parameters in the path string. | diff --git a/docs/en/resources/tools/looker/looker-add-dashboard-element.md b/docs/en/resources/tools/looker/looker-add-dashboard-element.md index 3c0a65f2d3d1..5e217fc8657f 100644 --- a/docs/en/resources/tools/looker/looker-add-dashboard-element.md +++ b/docs/en/resources/tools/looker/looker-add-dashboard-element.md @@ -25,42 +25,42 @@ It's compatible with the following sources: ## Example ```yaml -tools: - add_dashboard_element: - kind: looker-add-dashboard-element - source: looker-source - description: | - This tool creates a new tile (element) within an existing Looker dashboard. - Tiles are added in the order this tool is called for a given `dashboard_id`. +kind: tools +name: add_dashboard_element +type: looker-add-dashboard-element +source: looker-source +description: | + This tool creates a new tile (element) within an existing Looker dashboard. + Tiles are added in the order this tool is called for a given `dashboard_id`. - CRITICAL ORDER OF OPERATIONS: - 1. Create the dashboard using `make_dashboard`. - 2. Add any dashboard-level filters using `add_dashboard_filter`. - 3. Then, add elements (tiles) using this tool. + CRITICAL ORDER OF OPERATIONS: + 1. Create the dashboard using `make_dashboard`. + 2. Add any dashboard-level filters using `add_dashboard_filter`. + 3. Then, add elements (tiles) using this tool. - Required Parameters: - - dashboard_id: The ID of the target dashboard, obtained from `make_dashboard`. - - model_name, explore_name, fields: These query parameters are inherited - from the `query` tool and are required to define the data for the tile. + Required Parameters: + - dashboard_id: The ID of the target dashboard, obtained from `make_dashboard`. + - model_name, explore_name, fields: These query parameters are inherited + from the `query` tool and are required to define the data for the tile. - Optional Parameters: - - title: An optional title for the dashboard tile. - - pivots, filters, sorts, limit, query_timezone: These query parameters are - inherited from the `query` tool and can be used to customize the tile's query. - - vis_config: A JSON object defining the visualization settings for this tile. - The structure and options are the same as for the `query_url` tool's `vis_config`. + Optional Parameters: + - title: An optional title for the dashboard tile. + - pivots, filters, sorts, limit, query_timezone: These query parameters are + inherited from the `query` tool and can be used to customize the tile's query. + - vis_config: A JSON object defining the visualization settings for this tile. + The structure and options are the same as for the `query_url` tool's `vis_config`. - Connecting to Dashboard Filters: - A dashboard element can be connected to one or more dashboard filters (created with - `add_dashboard_filter`). To do this, specify the `name` of the dashboard filter - and the `field` from the element's query that the filter should apply to. - The format for specifying the field is `view_name.field_name`. + Connecting to Dashboard Filters: + A dashboard element can be connected to one or more dashboard filters (created with + `add_dashboard_filter`). To do this, specify the `name` of the dashboard filter + and the `field` from the element's query that the filter should apply to. + The format for specifying the field is `view_name.field_name`. ``` ## Reference | **field** | **type** | **required** | **description** | |:------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-add-dashboard-element". | +| type | string | true | Must be "looker-add-dashboard-element". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | \ No newline at end of file diff --git a/docs/en/resources/tools/looker/looker-add-dashboard-filter.md b/docs/en/resources/tools/looker/looker-add-dashboard-filter.md index e5cf5ba34de6..ca88afebfcb9 100644 --- a/docs/en/resources/tools/looker/looker-add-dashboard-filter.md +++ b/docs/en/resources/tools/looker/looker-add-dashboard-filter.md @@ -39,37 +39,37 @@ It's compatible with the following sources: ## Example ```yaml -tools: - add_dashboard_filter: - kind: looker-add-dashboard-filter - source: looker-source - description: | - This tool adds a filter to a Looker dashboard. +kind: tools +name: add_dashboard_filter +type: looker-add-dashboard-filter +source: looker-source +description: | + This tool adds a filter to a Looker dashboard. - CRITICAL ORDER OF OPERATIONS: - 1. Create a dashboard using `make_dashboard`. - 2. Add all desired filters using this tool (`add_dashboard_filter`). - 3. Finally, add dashboard elements (tiles) using `add_dashboard_element`. + CRITICAL ORDER OF OPERATIONS: + 1. Create a dashboard using `make_dashboard`. + 2. Add all desired filters using this tool (`add_dashboard_filter`). + 3. Finally, add dashboard elements (tiles) using `add_dashboard_element`. - Parameters: - - dashboard_id (required): The ID from `make_dashboard`. - - name (required): A unique internal identifier for the filter. You will use this `name` later in `add_dashboard_element` to bind tiles to this filter. - - title (required): The label displayed to users in the UI. - - filter_type (required): One of `date_filter`, `number_filter`, `string_filter`, or `field_filter`. - - default_value (optional): The initial value for the filter. + Parameters: + - dashboard_id (required): The ID from `make_dashboard`. + - name (required): A unique internal identifier for the filter. You will use this `name` later in `add_dashboard_element` to bind tiles to this filter. + - title (required): The label displayed to users in the UI. + - filter_type (required): One of `date_filter`, `number_filter`, `string_filter`, or `field_filter`. + - default_value (optional): The initial value for the filter. - Field Filters (`flter_type: field_filter`): - If creating a field filter, you must also provide: - - model - - explore - - dimension - The filter will inherit suggestions and type information from this LookML field. + Field Filters (`flter_type: field_filter`): + If creating a field filter, you must also provide: + - model + - explore + - dimension + The filter will inherit suggestions and type information from this LookML field. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-add-dashboard-filter". | +| type | string | true | Must be "looker-add-dashboard-filter". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | \ No newline at end of file diff --git a/docs/en/resources/tools/looker/looker-conversational-analytics.md b/docs/en/resources/tools/looker/looker-conversational-analytics.md index 150f347cf727..6e064cf7a46a 100644 --- a/docs/en/resources/tools/looker/looker-conversational-analytics.md +++ b/docs/en/resources/tools/looker/looker-conversational-analytics.md @@ -29,21 +29,21 @@ It's compatible with the following sources: ## Example ```yaml -tools: - ask_data_insights: - kind: looker-conversational-analytics - source: looker-source - description: | - Use this tool to ask questions about your data using the Looker Conversational - Analytics API. You must provide a natural language query and a list of - 1 to 5 model and explore combinations (e.g. [{'model': 'the_model', 'explore': 'the_explore'}]). - Use the 'get_models' and 'get_explores' tools to discover available models and explores. +kind: tools +name: ask_data_insights +type: looker-conversational-analytics +source: looker-source +description: | + Use this tool to ask questions about your data using the Looker Conversational + Analytics API. You must provide a natural language query and a list of + 1 to 5 model and explore combinations (e.g. [{'model': 'the_model', 'explore': 'the_explore'}]). + Use the 'get_models' and 'get_explores' tools to discover available models and explores. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "lookerca-conversational-analytics". | +| type | string | true | Must be "lookerca-conversational-analytics". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-create-project-file.md b/docs/en/resources/tools/looker/looker-create-project-file.md index 826dda98e9e4..3e36fe73d0f9 100644 --- a/docs/en/resources/tools/looker/looker-create-project-file.md +++ b/docs/en/resources/tools/looker/looker-create-project-file.md @@ -22,29 +22,29 @@ as well as the file content. ## Example ```yaml -tools: - create_project_file: - kind: looker-create-project-file - source: looker-source - description: | - This tool creates a new LookML file within a specified project, populating - it with the provided content. - - Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. - - Parameters: - - project_id (required): The unique ID of the LookML project. - - file_path (required): The desired path and filename for the new file within the project. - - content (required): The full LookML content to write into the new file. - - Output: - A confirmation message upon successful file creation. +kind: tools +name: create_project_file +type: looker-create-project-file +source: looker-source +description: | + This tool creates a new LookML file within a specified project, populating + it with the provided content. + + Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. + + Parameters: + - project_id (required): The unique ID of the LookML project. + - file_path (required): The desired path and filename for the new file within the project. + - content (required): The full LookML content to write into the new file. + + Output: + A confirmation message upon successful file creation. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-create-project-file". | +| type | string | true | Must be "looker-create-project-file". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-delete-project-file.md b/docs/en/resources/tools/looker/looker-delete-project-file.md index e5bf06948d41..11419b8a19d9 100644 --- a/docs/en/resources/tools/looker/looker-delete-project-file.md +++ b/docs/en/resources/tools/looker/looker-delete-project-file.md @@ -21,28 +21,28 @@ It's compatible with the following sources: ## Example ```yaml -tools: - delete_project_file: - kind: looker-delete-project-file - source: looker-source - description: | - This tool permanently deletes a specified LookML file from within a project. - Use with caution, as this action cannot be undone through the API. - - Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. - - Parameters: - - project_id (required): The unique ID of the LookML project. - - file_path (required): The exact path to the LookML file to delete within the project. - - Output: - A confirmation message upon successful file deletion. +kind: tools +name: delete_project_file +type: looker-delete-project-file +source: looker-source +description: | + This tool permanently deletes a specified LookML file from within a project. + Use with caution, as this action cannot be undone through the API. + + Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. + + Parameters: + - project_id (required): The unique ID of the LookML project. + - file_path (required): The exact path to the LookML file to delete within the project. + + Output: + A confirmation message upon successful file deletion. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-delete-project-file". | +| type | string | true | Must be "looker-delete-project-file". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-dev-mode.md b/docs/en/resources/tools/looker/looker-dev-mode.md index 9f69343ad5b0..33509ea54b04 100644 --- a/docs/en/resources/tools/looker/looker-dev-mode.md +++ b/docs/en/resources/tools/looker/looker-dev-mode.md @@ -22,24 +22,24 @@ to exit dev mode. ## Example ```yaml -tools: - dev_mode: - kind: looker-dev-mode - source: looker-source - description: | - This tool allows toggling the Looker IDE session between Development Mode and Production Mode. - Development Mode enables making and testing changes to LookML projects. - - Parameters: - - enable (required): A boolean value. - - `true`: Switches the current session to Development Mode. - - `false`: Switches the current session to Production Mode. +kind: tools +name: dev_mode +type: looker-dev-mode +source: looker-source +description: | + This tool allows toggling the Looker IDE session between Development Mode and Production Mode. + Development Mode enables making and testing changes to LookML projects. + + Parameters: + - enable (required): A boolean value. + - `true`: Switches the current session to Development Mode. + - `false`: Switches the current session to Production Mode. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-dev-mode". | +| type | string | true | Must be "looker-dev-mode". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-generate-embed-url.md b/docs/en/resources/tools/looker/looker-generate-embed-url.md index 1e136165dabe..bf7f4c1f2325 100644 --- a/docs/en/resources/tools/looker/looker-generate-embed-url.md +++ b/docs/en/resources/tools/looker/looker-generate-embed-url.md @@ -31,28 +31,28 @@ supplied to this tool. ## Example ```yaml -tools: - generate_embed_url: - kind: looker-generate-embed-url - source: looker-source - description: | - This tool generates a signed, private embed URL for specific Looker content, - allowing users to access it directly. - - Parameters: - - type (required): The type of content to embed. Common values include: - - `dashboards` - - `looks` - - `explore` - - id (required): The unique identifier for the content. - - For dashboards and looks, use the numeric ID (e.g., "123"). - - For explores, use the format "model_name/explore_name". +kind: tools +name: generate_embed_url +type: looker-generate-embed-url +source: looker-source +description: | + This tool generates a signed, private embed URL for specific Looker content, + allowing users to access it directly. + + Parameters: + - type (required): The type of content to embed. Common values include: + - `dashboards` + - `looks` + - `explore` + - id (required): The unique identifier for the content. + - For dashboards and looks, use the numeric ID (e.g., "123"). + - For explores, use the format "model_name/explore_name". ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-generate-embed-url" | +| type | string | true | Must be "looker-generate-embed-url" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-connection-databases.md b/docs/en/resources/tools/looker/looker-get-connection-databases.md index 23611fc2a16c..b46459c26ed8 100644 --- a/docs/en/resources/tools/looker/looker-get-connection-databases.md +++ b/docs/en/resources/tools/looker/looker-get-connection-databases.md @@ -21,27 +21,27 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_connection_databases: - kind: looker-get-connection-databases - source: looker-source - description: | - This tool retrieves a list of databases available through a specified Looker connection. - This is only applicable for connections that support multiple databases. - Use `get_connections` to check if a connection supports multiple databases. - - Parameters: - - connection_name (required): The name of the database connection, obtained from `get_connections`. - - Output: - A JSON array of strings, where each string is the name of an available database. - If the connection does not support multiple databases, an empty list or an error will be returned. +kind: tools +name: get_connection_databases +type: looker-get-connection-databases +source: looker-source +description: | + This tool retrieves a list of databases available through a specified Looker connection. + This is only applicable for connections that support multiple databases. + Use `get_connections` to check if a connection supports multiple databases. + + Parameters: + - connection_name (required): The name of the database connection, obtained from `get_connections`. + + Output: + A JSON array of strings, where each string is the name of an available database. + If the connection does not support multiple databases, an empty list or an error will be returned. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-connection-databases". | +| type | string | true | Must be "looker-get-connection-databases". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-connection-schemas.md b/docs/en/resources/tools/looker/looker-get-connection-schemas.md index 0ef34015c32e..de568b8e0e10 100644 --- a/docs/en/resources/tools/looker/looker-get-connection-schemas.md +++ b/docs/en/resources/tools/looker/looker-get-connection-schemas.md @@ -21,27 +21,27 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_connection_schemas: - kind: looker-get-connection-schemas - source: looker-source - description: | - This tool retrieves a list of database schemas available through a specified - Looker connection. - - Parameters: - - connection_name (required): The name of the database connection, obtained from `get_connections`. - - database (optional): An optional database name to filter the schemas. - Only applicable for connections that support multiple databases. - - Output: - A JSON array of strings, where each string is the name of an available schema. +kind: tools +name: get_connection_schemas +type: looker-get-connection-schemas +source: looker-source +description: | + This tool retrieves a list of database schemas available through a specified + Looker connection. + + Parameters: + - connection_name (required): The name of the database connection, obtained from `get_connections`. + - database (optional): An optional database name to filter the schemas. + Only applicable for connections that support multiple databases. + + Output: + A JSON array of strings, where each string is the name of an available schema. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-connection-schemas". | +| type | string | true | Must be "looker-get-connection-schemas". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-connection-table-columns.md b/docs/en/resources/tools/looker/looker-get-connection-table-columns.md index f4db6445fe88..8f19bd372b05 100644 --- a/docs/en/resources/tools/looker/looker-get-connection-table-columns.md +++ b/docs/en/resources/tools/looker/looker-get-connection-table-columns.md @@ -21,31 +21,31 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_connection_table_columns: - kind: looker-get-connection-table-columns - source: looker-source - description: | - This tool retrieves a list of columns for one or more specified tables within a - given database schema and connection. - - Parameters: - - connection_name (required): The name of the database connection, obtained from `get_connections`. - - schema (required): The name of the schema where the tables reside, obtained from `get_connection_schemas`. - - tables (required): A comma-separated string of table names for which to retrieve columns - (e.g., "users,orders,products"), obtained from `get_connection_tables`. - - database (optional): The name of the database to filter by. Only applicable for connections - that support multiple databases (check with `get_connections`). - - Output: - A JSON array of objects, where each object represents a column and contains details - such as `table_name`, `column_name`, `data_type`, and `is_nullable`. +kind: tools +name: get_connection_table_columns +type: looker-get-connection-table-columns +source: looker-source +description: | + This tool retrieves a list of columns for one or more specified tables within a + given database schema and connection. + + Parameters: + - connection_name (required): The name of the database connection, obtained from `get_connections`. + - schema (required): The name of the schema where the tables reside, obtained from `get_connection_schemas`. + - tables (required): A comma-separated string of table names for which to retrieve columns + (e.g., "users,orders,products"), obtained from `get_connection_tables`. + - database (optional): The name of the database to filter by. Only applicable for connections + that support multiple databases (check with `get_connections`). + + Output: + A JSON array of objects, where each object represents a column and contains details + such as `table_name`, `column_name`, `data_type`, and `is_nullable`. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-connection-table-columns". | +| type | string | true | Must be "looker-get-connection-table-columns". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-connection-tables.md b/docs/en/resources/tools/looker/looker-get-connection-tables.md index 86a2830cd9e8..5d191828bf71 100644 --- a/docs/en/resources/tools/looker/looker-get-connection-tables.md +++ b/docs/en/resources/tools/looker/looker-get-connection-tables.md @@ -22,28 +22,28 @@ and an optional `db` parameter. ## Example ```yaml -tools: - get_connection_tables: - kind: looker-get-connection-tables - source: looker-source - description: | - This tool retrieves a list of tables available within a specified database schema - through a Looker connection. - - Parameters: - - connection_name (required): The name of the database connection, obtained from `get_connections`. - - schema (required): The name of the schema to list tables from, obtained from `get_connection_schemas`. - - database (optional): The name of the database to filter by. Only applicable for connections - that support multiple databases (check with `get_connections`). - - Output: - A JSON array of strings, where each string is the name of an available table. +kind: tools +name: get_connection_tables +type: looker-get-connection-tables +source: looker-source +description: | + This tool retrieves a list of tables available within a specified database schema + through a Looker connection. + + Parameters: + - connection_name (required): The name of the database connection, obtained from `get_connections`. + - schema (required): The name of the schema to list tables from, obtained from `get_connection_schemas`. + - database (optional): The name of the database to filter by. Only applicable for connections + that support multiple databases (check with `get_connections`). + + Output: + A JSON array of strings, where each string is the name of an available table. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-connection-tables". | +| type | string | true | Must be "looker-get-connection-tables". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-connections.md b/docs/en/resources/tools/looker/looker-get-connections.md index c6c0159789c3..52a1c967805a 100644 --- a/docs/en/resources/tools/looker/looker-get-connections.md +++ b/docs/en/resources/tools/looker/looker-get-connections.md @@ -21,29 +21,29 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_connections: - kind: looker-get-connections - source: looker-source - description: | - This tool retrieves a list of all database connections configured in the Looker system. - - Parameters: - This tool takes no parameters. - - Output: - A JSON array of objects, each representing a database connection and including details such as: - - `name`: The connection's unique identifier. - - `dialect`: The database dialect (e.g., "mysql", "postgresql", "bigquery"). - - `default_schema`: The default schema for the connection. - - `database`: The associated database name (if applicable). - - `supports_multiple_databases`: A boolean indicating if the connection can access multiple databases. +kind: tools +name: get_connections +type: looker-get-connections +source: looker-source +description: | + This tool retrieves a list of all database connections configured in the Looker system. + + Parameters: + This tool takes no parameters. + + Output: + A JSON array of objects, each representing a database connection and including details such as: + - `name`: The connection's unique identifier. + - `dialect`: The database dialect (e.g., "mysql", "postgresql", "bigquery"). + - `default_schema`: The default schema for the connection. + - `database`: The associated database name (if applicable). + - `supports_multiple_databases`: A boolean indicating if the connection can access multiple databases. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-connections". | +| type | string | true | Must be "looker-get-connections". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-dashboards.md b/docs/en/resources/tools/looker/looker-get-dashboards.md index db5c9e532ebf..a8f117d27894 100644 --- a/docs/en/resources/tools/looker/looker-get-dashboards.md +++ b/docs/en/resources/tools/looker/looker-get-dashboards.md @@ -28,36 +28,36 @@ default to 100 and 0. ## Example ```yaml -tools: - get_dashboards: - kind: looker-get-dashboards - source: looker-source - description: | - This tool searches for saved dashboards in a Looker instance. It returns a list of JSON objects, each representing a dashboard. - - Search Parameters: - - title (optional): Filter by dashboard title (supports wildcards). - - folder_id (optional): Filter by the ID of the folder where the dashboard is saved. - - user_id (optional): Filter by the ID of the user who created the dashboard. - - description (optional): Filter by description content (supports wildcards). - - id (optional): Filter by specific dashboard ID. - - limit (optional): Maximum number of results to return. Defaults to a system limit. - - offset (optional): Starting point for pagination. - - String Search Behavior: - - Case-insensitive matching. - - Supports SQL LIKE pattern match wildcards: - - `%`: Matches any sequence of zero or more characters. (e.g., `"finan%"` matches "financial", "finance") - - `_`: Matches any single character. (e.g., `"s_les"` matches "sales") - - Special expressions for null checks: - - `"IS NULL"`: Matches dashboards where the field is null. - - `"NOT NULL"`: Excludes dashboards where the field is null. +kind: tools +name: get_dashboards +type: looker-get-dashboards +source: looker-source +description: | + This tool searches for saved dashboards in a Looker instance. It returns a list of JSON objects, each representing a dashboard. + + Search Parameters: + - title (optional): Filter by dashboard title (supports wildcards). + - folder_id (optional): Filter by the ID of the folder where the dashboard is saved. + - user_id (optional): Filter by the ID of the user who created the dashboard. + - description (optional): Filter by description content (supports wildcards). + - id (optional): Filter by specific dashboard ID. + - limit (optional): Maximum number of results to return. Defaults to a system limit. + - offset (optional): Starting point for pagination. + + String Search Behavior: + - Case-insensitive matching. + - Supports SQL LIKE pattern match wildcards: + - `%`: Matches any sequence of zero or more characters. (e.g., `"finan%"` matches "financial", "finance") + - `_`: Matches any single character. (e.g., `"s_les"` matches "sales") + - Special expressions for null checks: + - `"IS NULL"`: Matches dashboards where the field is null. + - `"NOT NULL"`: Excludes dashboards where the field is null. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-dashboards" | +| type | string | true | Must be "looker-get-dashboards" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-dimensions.md b/docs/en/resources/tools/looker/looker-get-dimensions.md index 17f3bb68f7e6..41a899eac76a 100644 --- a/docs/en/resources/tools/looker/looker-get-dimensions.md +++ b/docs/en/resources/tools/looker/looker-get-dimensions.md @@ -23,25 +23,25 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_dimensions: - kind: looker-get-dimensions - source: looker-source - description: | - This tool retrieves a list of dimensions defined within a specific Looker explore. - Dimensions are non-aggregatable attributes or characteristics of your data - (e.g., product name, order date, customer city) that can be used for grouping, - filtering, or segmenting query results. +kind: tools +name: get_dimensions +type: looker-get-dimensions +source: looker-source +description: | + This tool retrieves a list of dimensions defined within a specific Looker explore. + Dimensions are non-aggregatable attributes or characteristics of your data + (e.g., product name, order date, customer city) that can be used for grouping, + filtering, or segmenting query results. - Parameters: - - model_name (required): The name of the LookML model, obtained from `get_models`. - - explore_name (required): The name of the explore within the model, obtained from `get_explores`. + Parameters: + - model_name (required): The name of the LookML model, obtained from `get_models`. + - explore_name (required): The name of the explore within the model, obtained from `get_explores`. - Output Details: - - If a dimension includes a `suggestions` field, its contents are valid values - that can be used directly as filters for that dimension. - - If a `suggest_explore` and `suggest_dimension` are provided, you can query - that specified explore and dimension to retrieve a list of valid filter values. + Output Details: + - If a dimension includes a `suggestions` field, its contents are valid values + that can be used directly as filters for that dimension. + - If a `suggest_explore` and `suggest_dimension` are provided, you can query + that specified explore and dimension to retrieve a list of valid filter values. ``` @@ -66,6 +66,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-dimensions". | +| type | string | true | Must be "looker-get-dimensions". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-explores.md b/docs/en/resources/tools/looker/looker-get-explores.md index d92942de9d5d..3b7a695d1b99 100644 --- a/docs/en/resources/tools/looker/looker-get-explores.md +++ b/docs/en/resources/tools/looker/looker-get-explores.md @@ -35,24 +35,24 @@ The return type is an array of maps, each map is formatted like: ## Example ```yaml -tools: - get_explores: - kind: looker-get-explores - source: looker-source - description: | - This tool retrieves a list of explores defined within a specific LookML model. - Explores represent a curated view of your data, typically joining several - tables together to allow for focused analysis on a particular subject area. - The output provides details like the explore's `name` and `label`. - - Parameters: - - model_name (required): The name of the LookML model, obtained from `get_models`. +kind: tools +name: get_explores +type: looker-get-explores +source: looker-source +description: | + This tool retrieves a list of explores defined within a specific LookML model. + Explores represent a curated view of your data, typically joining several + tables together to allow for focused analysis on a particular subject area. + The output provides details like the explore's `name` and `label`. + + Parameters: + - model_name (required): The name of the LookML model, obtained from `get_models`. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-explores". | +| type | string | true | Must be "looker-get-explores". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-filters.md b/docs/en/resources/tools/looker/looker-get-filters.md index 2657936fd696..a455363de2fb 100644 --- a/docs/en/resources/tools/looker/looker-get-filters.md +++ b/docs/en/resources/tools/looker/looker-get-filters.md @@ -23,23 +23,23 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_filters: - kind: looker-get-filters - source: looker-source - description: | - This tool retrieves a list of "filter-only fields" defined within a specific - Looker explore. These are special fields defined in LookML specifically to - create user-facing filter controls that do not directly affect the `GROUP BY` - clause of the SQL query. They are often used in conjunction with liquid templating - to create dynamic queries. +kind: tools +name: get_filters +type: looker-get-filters +source: looker-source +description: | + This tool retrieves a list of "filter-only fields" defined within a specific + Looker explore. These are special fields defined in LookML specifically to + create user-facing filter controls that do not directly affect the `GROUP BY` + clause of the SQL query. They are often used in conjunction with liquid templating + to create dynamic queries. - Note: Regular dimensions and measures can also be used as filters in a query. - This tool *only* returns fields explicitly defined as `filter:` in LookML. + Note: Regular dimensions and measures can also be used as filters in a query. + This tool *only* returns fields explicitly defined as `filter:` in LookML. - Parameters: - - model_name (required): The name of the LookML model, obtained from `get_models`. - - explore_name (required): The name of the explore within the model, obtained from `get_explores`. + Parameters: + - model_name (required): The name of the LookML model, obtained from `get_models`. + - explore_name (required): The name of the explore within the model, obtained from `get_explores`. ``` The response is a json array with the following elements: @@ -63,6 +63,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-filters". | +| type | string | true | Must be "looker-get-filters". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-looks.md b/docs/en/resources/tools/looker/looker-get-looks.md index 06bc5f7856d3..a15f5f31ba36 100644 --- a/docs/en/resources/tools/looker/looker-get-looks.md +++ b/docs/en/resources/tools/looker/looker-get-looks.md @@ -29,37 +29,37 @@ default to 100 and 0. ## Example ```yaml -tools: - get_looks: - kind: looker-get-looks - source: looker-source - description: | - This tool searches for saved Looks (pre-defined queries and visualizations) - in a Looker instance. It returns a list of JSON objects, each representing a Look. +kind: tools +name: get_looks +type: looker-get-looks +source: looker-source +description: | + This tool searches for saved Looks (pre-defined queries and visualizations) + in a Looker instance. It returns a list of JSON objects, each representing a Look. - Search Parameters: - - title (optional): Filter by Look title (supports wildcards). - - folder_id (optional): Filter by the ID of the folder where the Look is saved. - - user_id (optional): Filter by the ID of the user who created the Look. - - description (optional): Filter by description content (supports wildcards). - - id (optional): Filter by specific Look ID. - - limit (optional): Maximum number of results to return. Defaults to a system limit. - - offset (optional): Starting point for pagination. + Search Parameters: + - title (optional): Filter by Look title (supports wildcards). + - folder_id (optional): Filter by the ID of the folder where the Look is saved. + - user_id (optional): Filter by the ID of the user who created the Look. + - description (optional): Filter by description content (supports wildcards). + - id (optional): Filter by specific Look ID. + - limit (optional): Maximum number of results to return. Defaults to a system limit. + - offset (optional): Starting point for pagination. - String Search Behavior: - - Case-insensitive matching. - - Supports SQL LIKE pattern match wildcards: - - `%`: Matches any sequence of zero or more characters. (e.g., `"dan%"` matches "danger", "Danzig") - - `_`: Matches any single character. (e.g., `"D_m%"` matches "Damage", "dump") - - Special expressions for null checks: - - `"IS NULL"`: Matches Looks where the field is null. - - `"NOT NULL"`: Excludes Looks where the field is null. + String Search Behavior: + - Case-insensitive matching. + - Supports SQL LIKE pattern match wildcards: + - `%`: Matches any sequence of zero or more characters. (e.g., `"dan%"` matches "danger", "Danzig") + - `_`: Matches any single character. (e.g., `"D_m%"` matches "Damage", "dump") + - Special expressions for null checks: + - `"IS NULL"`: Matches Looks where the field is null. + - `"NOT NULL"`: Excludes Looks where the field is null. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-looks" | +| type | string | true | Must be "looker-get-looks" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-measures.md b/docs/en/resources/tools/looker/looker-get-measures.md index 730403185511..bcc390a19ff0 100644 --- a/docs/en/resources/tools/looker/looker-get-measures.md +++ b/docs/en/resources/tools/looker/looker-get-measures.md @@ -23,24 +23,24 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_measures: - kind: looker-get-measures - source: looker-source - description: | - This tool retrieves a list of measures defined within a specific Looker explore. - Measures are aggregatable metrics (e.g., total sales, average price, count of users) - that are used for calculations and quantitative analysis in your queries. +kind: tools +name: get_measures +type: looker-get-measures +source: looker-source +description: | + This tool retrieves a list of measures defined within a specific Looker explore. + Measures are aggregatable metrics (e.g., total sales, average price, count of users) + that are used for calculations and quantitative analysis in your queries. - Parameters: - - model_name (required): The name of the LookML model, obtained from `get_models`. - - explore_name (required): The name of the explore within the model, obtained from `get_explores`. + Parameters: + - model_name (required): The name of the LookML model, obtained from `get_models`. + - explore_name (required): The name of the explore within the model, obtained from `get_explores`. - Output Details: - - If a measure includes a `suggestions` field, its contents are valid values - that can be used directly as filters for that measure. - - If a `suggest_explore` and `suggest_dimension` are provided, you can query - that specified explore and dimension to retrieve a list of valid filter values. + Output Details: + - If a measure includes a `suggestions` field, its contents are valid values + that can be used directly as filters for that measure. + - If a `suggest_explore` and `suggest_dimension` are provided, you can query + that specified explore and dimension to retrieve a list of valid filter values. ``` @@ -65,6 +65,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-measures". | +| type | string | true | Must be "looker-get-measures". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-models.md b/docs/en/resources/tools/looker/looker-get-models.md index 81002cf3a2e6..dbaf4563849e 100644 --- a/docs/en/resources/tools/looker/looker-get-models.md +++ b/docs/en/resources/tools/looker/looker-get-models.md @@ -21,23 +21,23 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_models: - kind: looker-get-models - source: looker-source - description: | - This tool retrieves a list of available LookML models in the Looker instance. - LookML models define the data structure and relationships that users can query. - The output includes details like the model's `name` and `label`, which are - essential for subsequent calls to tools like `get_explores` or `query`. - - This tool takes no parameters. +kind: tools +name: get_models +type: looker-get-models +source: looker-source +description: | + This tool retrieves a list of available LookML models in the Looker instance. + LookML models define the data structure and relationships that users can query. + The output includes details like the model's `name` and `label`, which are + essential for subsequent calls to tools like `get_explores` or `query`. + + This tool takes no parameters. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-models". | +| type | string | true | Must be "looker-get-models". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-parameters.md b/docs/en/resources/tools/looker/looker-get-parameters.md index f40398568d61..bc3413093bdb 100644 --- a/docs/en/resources/tools/looker/looker-get-parameters.md +++ b/docs/en/resources/tools/looker/looker-get-parameters.md @@ -23,20 +23,20 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_parameters: - kind: looker-get-parameters - source: looker-source - description: | - This tool retrieves a list of parameters defined within a specific Looker explore. - LookML parameters are dynamic input fields that allow users to influence query - behavior without directly modifying the underlying LookML. They are often used - with `liquid` templating to create flexible dashboards and reports, enabling - users to choose dimensions, measures, or other query components at runtime. +kind: tools +name: get_parameters +type: looker-get-parameters +source: looker-source +description: | + This tool retrieves a list of parameters defined within a specific Looker explore. + LookML parameters are dynamic input fields that allow users to influence query + behavior without directly modifying the underlying LookML. They are often used + with `liquid` templating to create flexible dashboards and reports, enabling + users to choose dimensions, measures, or other query components at runtime. - Parameters: - - model_name (required): The name of the LookML model, obtained from `get_models`. - - explore_name (required): The name of the explore within the model, obtained from `get_explores`. + Parameters: + - model_name (required): The name of the LookML model, obtained from `get_models`. + - explore_name (required): The name of the explore within the model, obtained from `get_explores`. ``` The response is a json array with the following elements: @@ -60,6 +60,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-parameters". | +| type | string | true | Must be "looker-get-parameters". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-project-file.md b/docs/en/resources/tools/looker/looker-get-project-file.md index 440615efa429..83f23ce08e2d 100644 --- a/docs/en/resources/tools/looker/looker-get-project-file.md +++ b/docs/en/resources/tools/looker/looker-get-project-file.md @@ -21,26 +21,26 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_project_file: - kind: looker-get-project-file - source: looker-source - description: | - This tool retrieves the raw content of a specific LookML file from within a project. - - Parameters: - - project_id (required): The unique ID of the LookML project, obtained from `get_projects`. - - file_path (required): The path to the LookML file within the project, - typically obtained from `get_project_files`. - - Output: - The raw text content of the specified LookML file. +kind: tools +name: get_project_file +type: looker-get-project-file +source: looker-source +description: | + This tool retrieves the raw content of a specific LookML file from within a project. + + Parameters: + - project_id (required): The unique ID of the LookML project, obtained from `get_projects`. + - file_path (required): The path to the LookML file within the project, + typically obtained from `get_project_files`. + + Output: + The raw text content of the specified LookML file. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-project-file". | +| type | string | true | Must be "looker-get-project-file". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-project-files.md b/docs/en/resources/tools/looker/looker-get-project-files.md index 48ea27322872..dc28e61e66ad 100644 --- a/docs/en/resources/tools/looker/looker-get-project-files.md +++ b/docs/en/resources/tools/looker/looker-get-project-files.md @@ -21,26 +21,26 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_project_files: - kind: looker-get-project-files - source: looker-source - description: | - This tool retrieves a list of all LookML files within a specified project, - providing details about each file. - - Parameters: - - project_id (required): The unique ID of the LookML project, obtained from `get_projects`. - - Output: - A JSON array of objects, each representing a LookML file and containing - details such as `path`, `id`, `type`, and `git_status`. +kind: tools +name: get_project_files +type: looker-get-project-files +source: looker-source +description: | + This tool retrieves a list of all LookML files within a specified project, + providing details about each file. + + Parameters: + - project_id (required): The unique ID of the LookML project, obtained from `get_projects`. + + Output: + A JSON array of objects, each representing a LookML file and containing + details such as `path`, `id`, `type`, and `git_status`. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-project-files". | +| type | string | true | Must be "looker-get-project-files". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-get-projects.md b/docs/en/resources/tools/looker/looker-get-projects.md index 7c582eeae084..f6ad8def9500 100644 --- a/docs/en/resources/tools/looker/looker-get-projects.md +++ b/docs/en/resources/tools/looker/looker-get-projects.md @@ -21,27 +21,27 @@ It's compatible with the following sources: ## Example ```yaml -tools: - get_projects: - kind: looker-get-projects - source: looker-source - description: | - This tool retrieves a list of all LookML projects available on the Looker instance. - It is useful for identifying projects before performing actions like retrieving - project files or making modifications. - - Parameters: - This tool takes no parameters. - - Output: - A JSON array of objects, each containing the `project_id` and `project_name` - for a LookML project. +kind: tools +name: get_projects +type: looker-get-projects +source: looker-source +description: | + This tool retrieves a list of all LookML projects available on the Looker instance. + It is useful for identifying projects before performing actions like retrieving + project files or making modifications. + + Parameters: + This tool takes no parameters. + + Output: + A JSON array of objects, each containing the `project_id` and `project_name` + for a LookML project. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-get-projects". | +| type | string | true | Must be "looker-get-projects". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-health-analyze.md b/docs/en/resources/tools/looker/looker-health-analyze.md index bc44d3f30104..59b2575c44dd 100644 --- a/docs/en/resources/tools/looker/looker-health-analyze.md +++ b/docs/en/resources/tools/looker/looker-health-analyze.md @@ -37,29 +37,29 @@ instance. The `action` parameter selects the type of analysis to perform: ## Example ```yaml -tools: - health_analyze: - kind: looker-health-analyze - source: looker-source - description: | - This tool calculates the usage statistics for Looker projects, models, and explores. +kind: tools +name: health_analyze +type: looker-health-analyze +source: looker-source +description: | + This tool calculates the usage statistics for Looker projects, models, and explores. - Parameters: - - action (required): The type of resource to analyze. Can be `"projects"`, `"models"`, or `"explores"`. - - project (optional): The specific project ID to analyze. - - model (optional): The specific model name to analyze. Requires `project` if used without `explore`. - - explore (optional): The specific explore name to analyze. Requires `model` if used. - - timeframe (optional): The lookback period in days for usage data. Defaults to `90` days. - - min_queries (optional): The minimum number of queries for a resource to be considered active. Defaults to `1`. + Parameters: + - action (required): The type of resource to analyze. Can be `"projects"`, `"models"`, or `"explores"`. + - project (optional): The specific project ID to analyze. + - model (optional): The specific model name to analyze. Requires `project` if used without `explore`. + - explore (optional): The specific explore name to analyze. Requires `model` if used. + - timeframe (optional): The lookback period in days for usage data. Defaults to `90` days. + - min_queries (optional): The minimum number of queries for a resource to be considered active. Defaults to `1`. - Output: - The result is a JSON object containing usage metrics for the specified resources. + Output: + The result is a JSON object containing usage metrics for the specified resources. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-health-analyze" | +| type | string | true | Must be "looker-health-analyze" | | source | string | true | Looker source name | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-health-pulse.md b/docs/en/resources/tools/looker/looker-health-pulse.md index ccbc05be34cb..1ef1ab6e140b 100644 --- a/docs/en/resources/tools/looker/looker-health-pulse.md +++ b/docs/en/resources/tools/looker/looker-health-pulse.md @@ -44,33 +44,33 @@ The `looker-health-pulse` tool performs health checks on a Looker instance. The ## Example ```yaml -tools: - health_pulse: - kind: looker-health-pulse - source: looker-source - description: | - This tool performs various health checks on a Looker instance. +kind: tools +name: health_pulse +type: looker-health-pulse +source: looker-source +description: | + This tool performs various health checks on a Looker instance. - Parameters: - - action (required): Specifies the type of health check to perform. - Choose one of the following: - - `check_db_connections`: Verifies database connectivity. - - `check_dashboard_performance`: Assesses dashboard loading performance. - - `check_dashboard_errors`: Identifies errors within dashboards. - - `check_explore_performance`: Evaluates explore query performance. - - `check_schedule_failures`: Reports on failed scheduled deliveries. - - `check_legacy_features`: Checks for the usage of legacy features. + Parameters: + - action (required): Specifies the type of health check to perform. + Choose one of the following: + - `check_db_connections`: Verifies database connectivity. + - `check_dashboard_performance`: Assesses dashboard loading performance. + - `check_dashboard_errors`: Identifies errors within dashboards. + - `check_explore_performance`: Evaluates explore query performance. + - `check_schedule_failures`: Reports on failed scheduled deliveries. + - `check_legacy_features`: Checks for the usage of legacy features. - Note on `check_legacy_features`: - This action is exclusively available in Looker Core instances. If invoked - on a non-Looker Core instance, it will return a notice rather than an error. - This notice should be considered normal behavior and not an indication of an issue. + Note on `check_legacy_features`: + This action is exclusively available in Looker Core instances. If invoked + on a non-Looker Core instance, it will return a notice rather than an error. + This notice should be considered normal behavior and not an indication of an issue. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-health-pulse" | +| type | string | true | Must be "looker-health-pulse" | | source | string | true | Looker source name | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-health-vacuum.md b/docs/en/resources/tools/looker/looker-health-vacuum.md index f4d635ccc536..dc9ec7545c48 100644 --- a/docs/en/resources/tools/looker/looker-health-vacuum.md +++ b/docs/en/resources/tools/looker/looker-health-vacuum.md @@ -34,28 +34,28 @@ Identify unnused fields (*in this case, less than 1 query in the last 20 days*) and joins in the `order_items` explore and `thelook` model ```yaml -tools: - health_vacuum: - kind: looker-health-vacuum - source: looker-source - description: | - This tool identifies and suggests LookML models or explores that can be - safely removed due to inactivity or low usage. - - Parameters: - - action (required): The type of resource to analyze for removal candidates. Can be `"models"` or `"explores"`. - - project (optional): The specific project ID to consider. - - model (optional): The specific model name to consider. Requires `project` if used without `explore`. - - explore (optional): The specific explore name to consider. Requires `model` if used. - - timeframe (optional): The lookback period in days to assess usage. Defaults to `90` days. - - min_queries (optional): The minimum number of queries for a resource to be considered active. Defaults to `1`. - - Output: - A JSON array of objects, each representing a model or explore that is a candidate for deletion due to low usage. +kind: tools +name: health_vacuum +type: looker-health-vacuum +source: looker-source +description: | + This tool identifies and suggests LookML models or explores that can be + safely removed due to inactivity or low usage. + + Parameters: + - action (required): The type of resource to analyze for removal candidates. Can be `"models"` or `"explores"`. + - project (optional): The specific project ID to consider. + - model (optional): The specific model name to consider. Requires `project` if used without `explore`. + - explore (optional): The specific explore name to consider. Requires `model` if used. + - timeframe (optional): The lookback period in days to assess usage. Defaults to `90` days. + - min_queries (optional): The minimum number of queries for a resource to be considered active. Defaults to `1`. + + Output: + A JSON array of objects, each representing a model or explore that is a candidate for deletion due to low usage. ``` | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-health-vacuum" | +| type | string | true | Must be "looker-health-vacuum" | | source | string | true | Looker source name | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-make-dashboard.md b/docs/en/resources/tools/looker/looker-make-dashboard.md index f8112bcd5dcd..3e7dc03dda26 100644 --- a/docs/en/resources/tools/looker/looker-make-dashboard.md +++ b/docs/en/resources/tools/looker/looker-make-dashboard.md @@ -27,30 +27,30 @@ It's compatible with the following sources: ## Example ```yaml -tools: - make_dashboard: - kind: looker-make-dashboard - source: looker-source - description: | - This tool creates a new, empty dashboard in Looker. Dashboards are stored - in the user's personal folder, and the dashboard name must be unique. - After creation, use `add_dashboard_filter` to add filters and - `add_dashboard_element` to add content tiles. - - Required Parameters: - - title (required): A unique title for the new dashboard. - - description (required): A brief description of the dashboard's purpose. - - Output: - A JSON object containing a link (`url`) to the newly created dashboard and - its unique `id`. This `dashboard_id` is crucial for subsequent calls to - `add_dashboard_filter` and `add_dashboard_element`. +kind: tools +name: make_dashboard +type: looker-make-dashboard +source: looker-source +description: | + This tool creates a new, empty dashboard in Looker. Dashboards are stored + in the user's personal folder, and the dashboard name must be unique. + After creation, use `add_dashboard_filter` to add filters and + `add_dashboard_element` to add content tiles. + + Required Parameters: + - title (required): A unique title for the new dashboard. + - description (required): A brief description of the dashboard's purpose. + + Output: + A JSON object containing a link (`url`) to the newly created dashboard and + its unique `id`. This `dashboard_id` is crucial for subsequent calls to + `add_dashboard_filter` and `add_dashboard_element`. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-make-dashboard" | +| type | string | true | Must be "looker-make-dashboard" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-make-look.md b/docs/en/resources/tools/looker/looker-make-look.md index 9c698984370b..58e8b09e0da7 100644 --- a/docs/en/resources/tools/looker/looker-make-look.md +++ b/docs/en/resources/tools/looker/looker-make-look.md @@ -36,35 +36,35 @@ It's compatible with the following sources: ## Example ```yaml -tools: - make_look: - kind: looker-make-look - source: looker-source - description: | - This tool creates a new Look (saved query with visualization) in Looker. - The Look will be saved in the user's personal folder, and its name must be unique. +kind: tools +name: make_look +type: looker-make-look +source: looker-source +description: | + This tool creates a new Look (saved query with visualization) in Looker. + The Look will be saved in the user's personal folder, and its name must be unique. - Required Parameters: - - title: A unique title for the new Look. - - description: A brief description of the Look's purpose. - - model_name: The name of the LookML model (from `get_models`). - - explore_name: The name of the explore (from `get_explores`). - - fields: A list of field names (dimensions, measures, filters, or parameters) to include in the query. + Required Parameters: + - title: A unique title for the new Look. + - description: A brief description of the Look's purpose. + - model_name: The name of the LookML model (from `get_models`). + - explore_name: The name of the explore (from `get_explores`). + - fields: A list of field names (dimensions, measures, filters, or parameters) to include in the query. - Optional Parameters: - - pivots, filters, sorts, limit, query_timezone: These parameters are identical - to those described for the `query` tool. - - vis_config: A JSON object defining the visualization settings for the Look. - The structure and options are the same as for the `query_url` tool's `vis_config`. + Optional Parameters: + - pivots, filters, sorts, limit, query_timezone: These parameters are identical + to those described for the `query` tool. + - vis_config: A JSON object defining the visualization settings for the Look. + The structure and options are the same as for the `query_url` tool's `vis_config`. - Output: - A JSON object containing a link (`url`) to the newly created Look, along with its `id` and `slug`. + Output: + A JSON object containing a link (`url`) to the newly created Look, along with its `id` and `slug`. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-make-look" | +| type | string | true | Must be "looker-make-look" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-query-sql.md b/docs/en/resources/tools/looker/looker-query-sql.md index 064464ea5d49..ca61df1007c0 100644 --- a/docs/en/resources/tools/looker/looker-query-sql.md +++ b/docs/en/resources/tools/looker/looker-query-sql.md @@ -36,28 +36,28 @@ to find MCP Toolbox queries. ## Example ```yaml -tools: - query_sql: - kind: looker-query-sql - source: looker-source - description: | - This tool generates the underlying SQL query that Looker would execute - against the database for a given set of parameters. It is useful for - understanding how Looker translates a request into SQL. - - Parameters: - All parameters for this tool are identical to those of the `query` tool. - This includes `model_name`, `explore_name`, `fields` (required), - and optional parameters like `pivots`, `filters`, `sorts`, `limit`, and `query_timezone`. - - Output: - The result of this tool is the raw SQL text. +kind: tools +name: query_sql +type: looker-query-sql +source: looker-source +description: | + This tool generates the underlying SQL query that Looker would execute + against the database for a given set of parameters. It is useful for + understanding how Looker translates a request into SQL. + + Parameters: + All parameters for this tool are identical to those of the `query` tool. + This includes `model_name`, `explore_name`, `fields` (required), + and optional parameters like `pivots`, `filters`, `sorts`, `limit`, and `query_timezone`. + + Output: + The result of this tool is the raw SQL text. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-query-sql" | +| type | string | true | Must be "looker-query-sql" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-query-url.md b/docs/en/resources/tools/looker/looker-query-url.md index af1f138509fc..b883a9c5d196 100644 --- a/docs/en/resources/tools/looker/looker-query-url.md +++ b/docs/en/resources/tools/looker/looker-query-url.md @@ -32,465 +32,465 @@ It's compatible with the following sources: ## Example ```yaml -tools: - query_url: - kind: looker-query-url - source: looker-source - description: | - This tool generates a shareable URL for a Looker query, allowing users to - explore the query further within the Looker UI. It returns the generated URL, - along with the `query_id` and `slug`. - - Parameters: - All query parameters (e.g., `model_name`, `explore_name`, `fields`, `pivots`, - `filters`, `sorts`, `limit`, `query_timezone`) are the same as the `query` tool. - - Additionally, it accepts an optional `vis_config` parameter: - - vis_config (optional): A JSON object that controls the default visualization - settings for the generated query. - - vis_config Details: - The `vis_config` object supports a wide range of properties for various chart types. - Here are some notes on making visualizations. - - ### Cartesian Charts (Area, Bar, Column, Line, Scatter) - - These chart types share a large number of configuration options. - - **General** - * `type`: The type of visualization (`looker_area`, `looker_bar`, `looker_column`, `looker_line`, `looker_scatter`). - * `series_types`: Override the chart type for individual series. - * `show_view_names`: Display view names in labels and tooltips (`true`/`false`). - * `series_labels`: Provide custom names for series. - - **Styling & Colors** - * `colors`: An array of color values to be used for the chart series. - * `series_colors`: A mapping of series names to specific color values. - * `color_application`: Advanced controls for color palette application (collection, palette, reverse, etc.). - * `font_size`: Font size for labels (e.g., '12px'). - - **Legend** - * `hide_legend`: Show or hide the chart legend (`true`/`false`). - * `legend_position`: Placement of the legend (`'center'`, `'left'`, `'right'`). - - **Axes** - * `swap_axes`: Swap the X and Y axes (`true`/`false`). - * `x_axis_scale`: Scale of the x-axis (`'auto'`, `'ordinal'`, `'linear'`, `'time'`). - * `x_axis_reversed`, `y_axis_reversed`: Reverse the direction of an axis (`true`/`false`). - * `x_axis_gridlines`, `y_axis_gridlines`: Display gridlines for an axis (`true`/`false`). - * `show_x_axis_label`, `show_y_axis_label`: Show or hide the axis title (`true`/`false`). - * `show_x_axis_ticks`, `show_y_axis_ticks`: Show or hide axis tick marks (`true`/`false`). - * `x_axis_label`, `y_axis_label`: Set a custom title for an axis. - * `x_axis_datetime_label`: A format string for datetime labels on the x-axis (e.g., `'%Y-%m'`). - * `x_padding_left`, `x_padding_right`: Adjust padding on the ends of the x-axis. - * `x_axis_label_rotation`, `x_axis_label_rotation_bar`: Set rotation for x-axis labels. - * `x_axis_zoom`, `y_axis_zoom`: Enable zooming on an axis (`true`/`false`). - * `y_axes`: An array of configuration objects for multiple y-axes. - - **Data & Series** - * `stacking`: How to stack series (`''` for none, `'normal'`, `'percent'`). - * `ordering`: Order of series in a stack (`'none'`, etc.). - * `limit_displayed_rows`: Enable or disable limiting the number of rows displayed (`true`/`false`). - * `limit_displayed_rows_values`: Configuration for the row limit (e.g., `{ "first_last": "first", "show_hide": "show", "num_rows": 10 }`). - * `discontinuous_nulls`: How to render null values in line charts (`true`/`false`). - * `point_style`: Style for points on line and area charts (`'none'`, `'circle'`, `'circle_outline'`). - * `series_point_styles`: Override point styles for individual series. - * `interpolation`: Line interpolation style (`'linear'`, `'monotone'`, `'step'`, etc.). - * `show_value_labels`: Display values on data points (`true`/`false`). - * `label_value_format`: A format string for value labels. - * `show_totals_labels`: Display total labels on stacked charts (`true`/`false`). - * `totals_color`: Color for total labels. - * `show_silhouette`: Display a "silhouette" of hidden series in stacked charts (`true`/`false`). - * `hidden_series`: An array of series names to hide from the visualization. - - **Scatter/Bubble Specific** - * `size_by_field`: The field used to determine the size of bubbles. - * `color_by_field`: The field used to determine the color of bubbles. - * `plot_size_by_field`: Whether to display the size-by field in the legend. - * `cluster_points`: Group nearby points into clusters (`true`/`false`). - * `quadrants_enabled`: Display quadrants on the chart (`true`/`false`). - * `quadrant_properties`: Configuration for quadrant labels and colors. - * `custom_quadrant_value_x`, `custom_quadrant_value_y`: Set quadrant boundaries as a percentage. - * `custom_quadrant_point_x`, `custom_quadrant_point_y`: Set quadrant boundaries to a specific value. - - **Miscellaneous** - * `reference_lines`: Configuration for displaying reference lines. - * `trend_lines`: Configuration for displaying trend lines. - * `trellis`: Configuration for creating trellis (small multiple) charts. - * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering interactions. - - ### Boxplot - - * Inherits most of the Cartesian chart options. - * `type`: Must be `looker_boxplot`. - - ### Funnel - - * `type`: Must be `looker_funnel`. - * `orientation`: How data is read (`'automatic'`, `'dataInRows'`, `'dataInColumns'`). - * `percentType`: How percentages are calculated (`'percentOfMaxValue'`, `'percentOfPriorRow'`). - * `labelPosition`, `valuePosition`, `percentPosition`: Placement of labels (`'left'`, `'right'`, `'inline'`, `'hidden'`). - * `labelColor`, `labelColorEnabled`: Set a custom color for labels. - * `labelOverlap`: Allow labels to overlap (`true`/`false`). - * `barColors`: An array of colors for the funnel steps. - * `color_application`: Advanced color palette controls. - * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. - - ### Pie / Donut - - * `type`: Must be `looker_pie`. - * `value_labels`: Where to display values (`'legend'`, `'labels'`). - * `label_type`: The format of data labels (`'labPer'`, `'labVal'`, `'lab'`, `'val'`, `'per'`). - * `start_angle`, `end_angle`: The start and end angles of the pie chart. - * `inner_radius`: The inner radius, used to create a donut chart. - * `series_colors`, `series_labels`: Override colors and labels for specific slices. - * `color_application`: Advanced color palette controls. - * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. - * `advanced_vis_config`: A string containing JSON for advanced Highcharts configuration. - - ### Waterfall - - * Inherits most of the Cartesian chart options. - * `type`: Must be `looker_waterfall`. - * `up_color`: Color for positive (increasing) values. - * `down_color`: Color for negative (decreasing) values. - * `total_color`: Color for the total bar. - - ### Word Cloud - - * `type`: Must be `looker_wordcloud`. - * `rotation`: Enable random word rotation (`true`/`false`). - * `colors`: An array of colors for the words. - * `color_application`: Advanced color palette controls. - * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. - - These are some sample vis_config settings. - - A bar chart - - {{ - "defaults_version": 1, - "label_density": 25, - "legend_position": "center", - "limit_displayed_rows": false, - "ordering": "none", - "plot_size_by_field": false, - "point_style": "none", - "show_null_labels": false, - "show_silhouette": false, - "show_totals_labels": false, - "show_value_labels": false, - "show_view_names": false, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "stacking": "normal", - "totals_color": "#808080", - "trellis": "", - "type": "looker_bar", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "x_axis_zoom": true, - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5, - "y_axis_zoom": true - }} - - A column chart with an option advanced_vis_config - - {{ - "advanced_vis_config": "{ chart: { type: 'pie', spacingBottom: 50, spacingLeft: 50, spacingRight: 50, spacingTop: 50, }, legend: { enabled: false, }, plotOptions: { pie: { dataLabels: { enabled: true, format: '\u003cb\u003e{key}\u003c/b\u003e\u003cspan style=\"font-weight: normal\"\u003e - {percentage:.2f}%\u003c/span\u003e', }, showInLegend: false, }, }, series: [], }", - "colors": [ - "grey" - ], - "defaults_version": 1, - "hidden_fields": [], - "label_density": 25, - "legend_position": "center", - "limit_displayed_rows": false, - "note_display": "below", - "note_state": "collapsed", - "note_text": "Unsold inventory only", - "ordering": "none", - "plot_size_by_field": false, - "point_style": "none", - "series_colors": {}, - "show_null_labels": false, - "show_silhouette": false, - "show_totals_labels": false, - "show_value_labels": true, - "show_view_names": false, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "stacking": "normal", - "totals_color": "#808080", - "trellis": "", - "type": "looker_column", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "x_axis_zoom": true, - "y_axes": [], - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5, - "y_axis_zoom": true - }} - - A line chart - - {{ - "defaults_version": 1, - "hidden_pivots": {}, - "hidden_series": [], - "interpolation": "linear", - "label_density": 25, - "legend_position": "center", - "limit_displayed_rows": false, - "plot_size_by_field": false, - "point_style": "none", - "series_types": {}, - "show_null_points": true, - "show_value_labels": false, - "show_view_names": false, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "stacking": "", - "trellis": "", - "type": "looker_line", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5 - }} - - An area chart - - {{ - "defaults_version": 1, - "interpolation": "linear", - "label_density": 25, - "legend_position": "center", - "limit_displayed_rows": false, - "plot_size_by_field": false, - "point_style": "none", - "series_types": {}, - "show_null_points": true, - "show_silhouette": false, - "show_totals_labels": false, - "show_value_labels": false, - "show_view_names": false, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "stacking": "normal", - "totals_color": "#808080", - "trellis": "", - "type": "looker_area", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "x_axis_zoom": true, - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5, - "y_axis_zoom": true - }} - - A scatter plot - - {{ - "cluster_points": false, - "custom_quadrant_point_x": 5, - "custom_quadrant_point_y": 5, - "custom_value_label_column": "", - "custom_x_column": "", - "custom_y_column": "", - "defaults_version": 1, - "hidden_fields": [], - "hidden_pivots": {}, - "hidden_points_if_no": [], - "hidden_series": [], - "interpolation": "linear", - "label_density": 25, - "legend_position": "center", - "limit_displayed_rows": false, - "limit_displayed_rows_values": { - "first_last": "first", - "num_rows": 0, - "show_hide": "hide" - }, - "plot_size_by_field": false, - "point_style": "circle", - "quadrant_properties": { - "0": { - "color": "", - "label": "Quadrant 1" - }, - "1": { - "color": "", - "label": "Quadrant 2" - }, - "2": { - "color": "", - "label": "Quadrant 3" - }, - "3": { - "color": "", - "label": "Quadrant 4" - } - }, - "quadrants_enabled": false, - "series_labels": {}, - "series_types": {}, - "show_null_points": false, - "show_value_labels": false, - "show_view_names": true, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "size_by_field": "roi", - "stacking": "normal", - "swap_axes": true, - "trellis": "", - "type": "looker_scatter", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "x_axis_zoom": true, - "y_axes": [ - { - "label": "", - "orientation": "bottom", - "series": [ - { - "axisId": "Channel_0 - average_of_roi_first", - "id": "Channel_0 - average_of_roi_first", - "name": "Channel_0" - }, - { - "axisId": "Channel_1 - average_of_roi_first", - "id": "Channel_1 - average_of_roi_first", - "name": "Channel_1" - }, - { - "axisId": "Channel_2 - average_of_roi_first", - "id": "Channel_2 - average_of_roi_first", - "name": "Channel_2" - }, - { - "axisId": "Channel_3 - average_of_roi_first", - "id": "Channel_3 - average_of_roi_first", - "name": "Channel_3" - }, - { - "axisId": "Channel_4 - average_of_roi_first", - "id": "Channel_4 - average_of_roi_first", - "name": "Channel_4" - } - ], - "showLabels": true, - "showValues": true, - "tickDensity": "custom", - "tickDensityCustom": 100, - "type": "linear", - "unpinAxis": false - } - ], - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5, - "y_axis_zoom": true - }} - - A single record visualization - - {{ - "defaults_version": 1, - "show_view_names": false, - "type": "looker_single_record" - }} - - A single value visualization - - {{ - "comparison_reverse_colors": false, - "comparison_type": "value", "conditional_formatting_include_nulls": false, "conditional_formatting_include_totals": false, - "custom_color": "#1A73E8", - "custom_color_enabled": true, - "defaults_version": 1, - "enable_conditional_formatting": false, - "series_types": {}, - "show_comparison": false, - "show_comparison_label": true, - "show_single_value_title": true, - "single_value_title": "Total Clicks", - "type": "single_value" - }} - - A Pie chart - - {{ - "defaults_version": 1, - "label_density": 25, - "label_type": "labPer", - "legend_position": "center", - "limit_displayed_rows": false, - "ordering": "none", - "plot_size_by_field": false, - "point_style": "none", - "series_types": {}, - "show_null_labels": false, - "show_silhouette": false, - "show_totals_labels": false, - "show_value_labels": false, - "show_view_names": false, - "show_x_axis_label": true, - "show_x_axis_ticks": true, - "show_y_axis_labels": true, - "show_y_axis_ticks": true, - "stacking": "", - "totals_color": "#808080", - "trellis": "", - "type": "looker_pie", - "value_labels": "legend", - "x_axis_gridlines": false, - "x_axis_reversed": false, - "x_axis_scale": "auto", - "y_axis_combined": true, - "y_axis_gridlines": true, - "y_axis_reversed": false, - "y_axis_scale_mode": "linear", - "y_axis_tick_density": "default", - "y_axis_tick_density_custom": 5 - }} - - The result is a JSON object with the id, slug, the url, and - the long_url. +kind: tools +name: query_url +type: looker-query-url +source: looker-source +description: | + This tool generates a shareable URL for a Looker query, allowing users to + explore the query further within the Looker UI. It returns the generated URL, + along with the `query_id` and `slug`. + + Parameters: + All query parameters (e.g., `model_name`, `explore_name`, `fields`, `pivots`, + `filters`, `sorts`, `limit`, `query_timezone`) are the same as the `query` tool. + + Additionally, it accepts an optional `vis_config` parameter: + - vis_config (optional): A JSON object that controls the default visualization + settings for the generated query. + + vis_config Details: + The `vis_config` object supports a wide range of properties for various chart types. + Here are some notes on making visualizations. + + ### Cartesian Charts (Area, Bar, Column, Line, Scatter) + + These chart types share a large number of configuration options. + + **General** + * `type`: The type of visualization (`looker_area`, `looker_bar`, `looker_column`, `looker_line`, `looker_scatter`). + * `series_types`: Override the chart type for individual series. + * `show_view_names`: Display view names in labels and tooltips (`true`/`false`). + * `series_labels`: Provide custom names for series. + + **Styling & Colors** + * `colors`: An array of color values to be used for the chart series. + * `series_colors`: A mapping of series names to specific color values. + * `color_application`: Advanced controls for color palette application (collection, palette, reverse, etc.). + * `font_size`: Font size for labels (e.g., '12px'). + + **Legend** + * `hide_legend`: Show or hide the chart legend (`true`/`false`). + * `legend_position`: Placement of the legend (`'center'`, `'left'`, `'right'`). + + **Axes** + * `swap_axes`: Swap the X and Y axes (`true`/`false`). + * `x_axis_scale`: Scale of the x-axis (`'auto'`, `'ordinal'`, `'linear'`, `'time'`). + * `x_axis_reversed`, `y_axis_reversed`: Reverse the direction of an axis (`true`/`false`). + * `x_axis_gridlines`, `y_axis_gridlines`: Display gridlines for an axis (`true`/`false`). + * `show_x_axis_label`, `show_y_axis_label`: Show or hide the axis title (`true`/`false`). + * `show_x_axis_ticks`, `show_y_axis_ticks`: Show or hide axis tick marks (`true`/`false`). + * `x_axis_label`, `y_axis_label`: Set a custom title for an axis. + * `x_axis_datetime_label`: A format string for datetime labels on the x-axis (e.g., `'%Y-%m'`). + * `x_padding_left`, `x_padding_right`: Adjust padding on the ends of the x-axis. + * `x_axis_label_rotation`, `x_axis_label_rotation_bar`: Set rotation for x-axis labels. + * `x_axis_zoom`, `y_axis_zoom`: Enable zooming on an axis (`true`/`false`). + * `y_axes`: An array of configuration objects for multiple y-axes. + + **Data & Series** + * `stacking`: How to stack series (`''` for none, `'normal'`, `'percent'`). + * `ordering`: Order of series in a stack (`'none'`, etc.). + * `limit_displayed_rows`: Enable or disable limiting the number of rows displayed (`true`/`false`). + * `limit_displayed_rows_values`: Configuration for the row limit (e.g., `{ "first_last": "first", "show_hide": "show", "num_rows": 10 }`). + * `discontinuous_nulls`: How to render null values in line charts (`true`/`false`). + * `point_style`: Style for points on line and area charts (`'none'`, `'circle'`, `'circle_outline'`). + * `series_point_styles`: Override point styles for individual series. + * `interpolation`: Line interpolation style (`'linear'`, `'monotone'`, `'step'`, etc.). + * `show_value_labels`: Display values on data points (`true`/`false`). + * `label_value_format`: A format string for value labels. + * `show_totals_labels`: Display total labels on stacked charts (`true`/`false`). + * `totals_color`: Color for total labels. + * `show_silhouette`: Display a "silhouette" of hidden series in stacked charts (`true`/`false`). + * `hidden_series`: An array of series names to hide from the visualization. + + **Scatter/Bubble Specific** + * `size_by_field`: The field used to determine the size of bubbles. + * `color_by_field`: The field used to determine the color of bubbles. + * `plot_size_by_field`: Whether to display the size-by field in the legend. + * `cluster_points`: Group nearby points into clusters (`true`/`false`). + * `quadrants_enabled`: Display quadrants on the chart (`true`/`false`). + * `quadrant_properties`: Configuration for quadrant labels and colors. + * `custom_quadrant_value_x`, `custom_quadrant_value_y`: Set quadrant boundaries as a percentage. + * `custom_quadrant_point_x`, `custom_quadrant_point_y`: Set quadrant boundaries to a specific value. + + **Miscellaneous** + * `reference_lines`: Configuration for displaying reference lines. + * `trend_lines`: Configuration for displaying trend lines. + * `trellis`: Configuration for creating trellis (small multiple) charts. + * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering interactions. + + ### Boxplot + + * Inherits most of the Cartesian chart options. + * `type`: Must be `looker_boxplot`. + + ### Funnel + + * `type`: Must be `looker_funnel`. + * `orientation`: How data is read (`'automatic'`, `'dataInRows'`, `'dataInColumns'`). + * `percentType`: How percentages are calculated (`'percentOfMaxValue'`, `'percentOfPriorRow'`). + * `labelPosition`, `valuePosition`, `percentPosition`: Placement of labels (`'left'`, `'right'`, `'inline'`, `'hidden'`). + * `labelColor`, `labelColorEnabled`: Set a custom color for labels. + * `labelOverlap`: Allow labels to overlap (`true`/`false`). + * `barColors`: An array of colors for the funnel steps. + * `color_application`: Advanced color palette controls. + * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. + + ### Pie / Donut + + * `type`: Must be `looker_pie`. + * `value_labels`: Where to display values (`'legend'`, `'labels'`). + * `label_type`: The format of data labels (`'labPer'`, `'labVal'`, `'lab'`, `'val'`, `'per'`). + * `start_angle`, `end_angle`: The start and end angles of the pie chart. + * `inner_radius`: The inner radius, used to create a donut chart. + * `series_colors`, `series_labels`: Override colors and labels for specific slices. + * `color_application`: Advanced color palette controls. + * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. + * `advanced_vis_config`: A string containing JSON for advanced Highcharts configuration. + + ### Waterfall + + * Inherits most of the Cartesian chart options. + * `type`: Must be `looker_waterfall`. + * `up_color`: Color for positive (increasing) values. + * `down_color`: Color for negative (decreasing) values. + * `total_color`: Color for the total bar. + + ### Word Cloud + + * `type`: Must be `looker_wordcloud`. + * `rotation`: Enable random word rotation (`true`/`false`). + * `colors`: An array of colors for the words. + * `color_application`: Advanced color palette controls. + * `crossfilterEnabled`, `crossfilters`: Configuration for cross-filtering. + + These are some sample vis_config settings. + + A bar chart - + {{ + "defaults_version": 1, + "label_density": 25, + "legend_position": "center", + "limit_displayed_rows": false, + "ordering": "none", + "plot_size_by_field": false, + "point_style": "none", + "show_null_labels": false, + "show_silhouette": false, + "show_totals_labels": false, + "show_value_labels": false, + "show_view_names": false, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "stacking": "normal", + "totals_color": "#808080", + "trellis": "", + "type": "looker_bar", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "x_axis_zoom": true, + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5, + "y_axis_zoom": true + }} + + A column chart with an option advanced_vis_config - + {{ + "advanced_vis_config": "{ chart: { type: 'pie', spacingBottom: 50, spacingLeft: 50, spacingRight: 50, spacingTop: 50, }, legend: { enabled: false, }, plotOptions: { pie: { dataLabels: { enabled: true, format: '\u003cb\u003e{key}\u003c/b\u003e\u003cspan style=\"font-weight: normal\"\u003e - {percentage:.2f}%\u003c/span\u003e', }, showInLegend: false, }, }, series: [], }", + "colors": [ + "grey" + ], + "defaults_version": 1, + "hidden_fields": [], + "label_density": 25, + "legend_position": "center", + "limit_displayed_rows": false, + "note_display": "below", + "note_state": "collapsed", + "note_text": "Unsold inventory only", + "ordering": "none", + "plot_size_by_field": false, + "point_style": "none", + "series_colors": {}, + "show_null_labels": false, + "show_silhouette": false, + "show_totals_labels": false, + "show_value_labels": true, + "show_view_names": false, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "stacking": "normal", + "totals_color": "#808080", + "trellis": "", + "type": "looker_column", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "x_axis_zoom": true, + "y_axes": [], + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5, + "y_axis_zoom": true + }} + + A line chart - + {{ + "defaults_version": 1, + "hidden_pivots": {}, + "hidden_series": [], + "interpolation": "linear", + "label_density": 25, + "legend_position": "center", + "limit_displayed_rows": false, + "plot_size_by_field": false, + "point_style": "none", + "series_types": {}, + "show_null_points": true, + "show_value_labels": false, + "show_view_names": false, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "stacking": "", + "trellis": "", + "type": "looker_line", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5 + }} + + An area chart - + {{ + "defaults_version": 1, + "interpolation": "linear", + "label_density": 25, + "legend_position": "center", + "limit_displayed_rows": false, + "plot_size_by_field": false, + "point_style": "none", + "series_types": {}, + "show_null_points": true, + "show_silhouette": false, + "show_totals_labels": false, + "show_value_labels": false, + "show_view_names": false, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "stacking": "normal", + "totals_color": "#808080", + "trellis": "", + "type": "looker_area", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "x_axis_zoom": true, + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5, + "y_axis_zoom": true + }} + + A scatter plot - + {{ + "cluster_points": false, + "custom_quadrant_point_x": 5, + "custom_quadrant_point_y": 5, + "custom_value_label_column": "", + "custom_x_column": "", + "custom_y_column": "", + "defaults_version": 1, + "hidden_fields": [], + "hidden_pivots": {}, + "hidden_points_if_no": [], + "hidden_series": [], + "interpolation": "linear", + "label_density": 25, + "legend_position": "center", + "limit_displayed_rows": false, + "limit_displayed_rows_values": { + "first_last": "first", + "num_rows": 0, + "show_hide": "hide" + }, + "plot_size_by_field": false, + "point_style": "circle", + "quadrant_properties": { + "0": { + "color": "", + "label": "Quadrant 1" + }, + "1": { + "color": "", + "label": "Quadrant 2" + }, + "2": { + "color": "", + "label": "Quadrant 3" + }, + "3": { + "color": "", + "label": "Quadrant 4" + } + }, + "quadrants_enabled": false, + "series_labels": {}, + "series_types": {}, + "show_null_points": false, + "show_value_labels": false, + "show_view_names": true, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "size_by_field": "roi", + "stacking": "normal", + "swap_axes": true, + "trellis": "", + "type": "looker_scatter", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "x_axis_zoom": true, + "y_axes": [ + { + "label": "", + "orientation": "bottom", + "series": [ + { + "axisId": "Channel_0 - average_of_roi_first", + "id": "Channel_0 - average_of_roi_first", + "name": "Channel_0" + }, + { + "axisId": "Channel_1 - average_of_roi_first", + "id": "Channel_1 - average_of_roi_first", + "name": "Channel_1" + }, + { + "axisId": "Channel_2 - average_of_roi_first", + "id": "Channel_2 - average_of_roi_first", + "name": "Channel_2" + }, + { + "axisId": "Channel_3 - average_of_roi_first", + "id": "Channel_3 - average_of_roi_first", + "name": "Channel_3" + }, + { + "axisId": "Channel_4 - average_of_roi_first", + "id": "Channel_4 - average_of_roi_first", + "name": "Channel_4" + } + ], + "showLabels": true, + "showValues": true, + "tickDensity": "custom", + "tickDensityCustom": 100, + "type": "linear", + "unpinAxis": false + } + ], + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5, + "y_axis_zoom": true + }} + + A single record visualization - + {{ + "defaults_version": 1, + "show_view_names": false, + "type": "looker_single_record" + }} + + A single value visualization - + {{ + "comparison_reverse_colors": false, + "comparison_type": "value", "conditional_formatting_include_nulls": false, "conditional_formatting_include_totals": false, + "custom_color": "#1A73E8", + "custom_color_enabled": true, + "defaults_version": 1, + "enable_conditional_formatting": false, + "series_types": {}, + "show_comparison": false, + "show_comparison_label": true, + "show_single_value_title": true, + "single_value_title": "Total Clicks", + "type": "single_value" + }} + + A Pie chart - + {{ + "defaults_version": 1, + "label_density": 25, + "label_type": "labPer", + "legend_position": "center", + "limit_displayed_rows": false, + "ordering": "none", + "plot_size_by_field": false, + "point_style": "none", + "series_types": {}, + "show_null_labels": false, + "show_silhouette": false, + "show_totals_labels": false, + "show_value_labels": false, + "show_view_names": false, + "show_x_axis_label": true, + "show_x_axis_ticks": true, + "show_y_axis_labels": true, + "show_y_axis_ticks": true, + "stacking": "", + "totals_color": "#808080", + "trellis": "", + "type": "looker_pie", + "value_labels": "legend", + "x_axis_gridlines": false, + "x_axis_reversed": false, + "x_axis_scale": "auto", + "y_axis_combined": true, + "y_axis_gridlines": true, + "y_axis_reversed": false, + "y_axis_scale_mode": "linear", + "y_axis_tick_density": "default", + "y_axis_tick_density_custom": 5 + }} + + The result is a JSON object with the id, slug, the url, and + the long_url. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-query-url" | +| type | string | true | Must be "looker-query-url" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-query.md b/docs/en/resources/tools/looker/looker-query.md index 7ba329276347..6fe10c0a2ec5 100644 --- a/docs/en/resources/tools/looker/looker-query.md +++ b/docs/en/resources/tools/looker/looker-query.md @@ -36,37 +36,37 @@ to find MCP Toolbox queries. ## Example ```yaml -tools: - query: - kind: looker-query - source: looker-source - description: | - This tool runs a query against a LookML model and returns the results in JSON format. +kind: tools +name: query +type: looker-query +source: looker-source +description: | + This tool runs a query against a LookML model and returns the results in JSON format. - Required Parameters: - - model_name: The name of the LookML model (from `get_models`). - - explore_name: The name of the explore (from `get_explores`). - - fields: A list of field names (dimensions, measures, filters, or parameters) to include in the query. + Required Parameters: + - model_name: The name of the LookML model (from `get_models`). + - explore_name: The name of the explore (from `get_explores`). + - fields: A list of field names (dimensions, measures, filters, or parameters) to include in the query. - Optional Parameters: - - pivots: A list of fields to pivot the results by. These fields must also be included in the `fields` list. - - filters: A map of filter expressions, e.g., `{"view.field": "value", "view.date": "7 days"}`. - - Do not quote field names. - - Use `not null` instead of `-NULL`. - - If a value contains a comma, enclose it in single quotes (e.g., "'New York, NY'"). - - sorts: A list of fields to sort by, optionally including direction (e.g., `["view.field desc"]`). - - limit: Row limit (default 500). Use "-1" for unlimited. - - query_timezone: specific timezone for the query (e.g. `America/Los_Angeles`). + Optional Parameters: + - pivots: A list of fields to pivot the results by. These fields must also be included in the `fields` list. + - filters: A map of filter expressions, e.g., `{"view.field": "value", "view.date": "7 days"}`. + - Do not quote field names. + - Use `not null` instead of `-NULL`. + - If a value contains a comma, enclose it in single quotes (e.g., "'New York, NY'"). + - sorts: A list of fields to sort by, optionally including direction (e.g., `["view.field desc"]`). + - limit: Row limit (default 500). Use "-1" for unlimited. + - query_timezone: specific timezone for the query (e.g. `America/Los_Angeles`). - Note: Use `get_dimensions`, `get_measures`, `get_filters`, and `get_parameters` to find valid fields. + Note: Use `get_dimensions`, `get_measures`, `get_filters`, and `get_parameters` to find valid fields. - The result of the query tool is JSON + The result of the query tool is JSON ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-query" | +| type | string | true | Must be "looker-query" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-run-dashboard.md b/docs/en/resources/tools/looker/looker-run-dashboard.md index cc2c2072dfd5..2682977b4939 100644 --- a/docs/en/resources/tools/looker/looker-run-dashboard.md +++ b/docs/en/resources/tools/looker/looker-run-dashboard.md @@ -22,26 +22,26 @@ It's compatible with the following sources: ## Example ```yaml -tools: - run_dashboard: - kind: looker-run-dashboard - source: looker-source - description: | - This tool executes the queries associated with each tile in a specified dashboard - and returns the aggregated data in a JSON structure. - - Parameters: - - dashboard_id (required): The unique identifier of the dashboard to run, - typically obtained from the `get_dashboards` tool. - - Output: - The data from all dashboard tiles is returned as a JSON object. +kind: tools +name: run_dashboard +type: looker-run-dashboard +source: looker-source +description: | + This tool executes the queries associated with each tile in a specified dashboard + and returns the aggregated data in a JSON structure. + + Parameters: + - dashboard_id (required): The unique identifier of the dashboard to run, + typically obtained from the `get_dashboards` tool. + + Output: + The data from all dashboard tiles is returned as a JSON object. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-run-dashboard" | +| type | string | true | Must be "looker-run-dashboard" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-run-look.md b/docs/en/resources/tools/looker/looker-run-look.md index eb2f57eedb05..f2a29893232d 100644 --- a/docs/en/resources/tools/looker/looker-run-look.md +++ b/docs/en/resources/tools/looker/looker-run-look.md @@ -22,26 +22,26 @@ It's compatible with the following sources: ## Example ```yaml -tools: - run_look: - kind: looker-run-look - source: looker-source - description: | - This tool executes the query associated with a saved Look and - returns the resulting data in a JSON structure. - - Parameters: - - look_id (required): The unique identifier of the Look to run, - typically obtained from the `get_looks` tool. - - Output: - The query results are returned as a JSON object. +kind: tools +name: run_look +type: looker-run-look +source: looker-source +description: | + This tool executes the query associated with a saved Look and + returns the resulting data in a JSON structure. + + Parameters: + - look_id (required): The unique identifier of the Look to run, + typically obtained from the `get_looks` tool. + + Output: + The query results are returned as a JSON object. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-run-look" | +| type | string | true | Must be "looker-run-look" | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/looker/looker-update-project-file.md b/docs/en/resources/tools/looker/looker-update-project-file.md index af8cabd81bcc..de4b092f1cc9 100644 --- a/docs/en/resources/tools/looker/looker-update-project-file.md +++ b/docs/en/resources/tools/looker/looker-update-project-file.md @@ -22,28 +22,28 @@ as well as the new file content. ## Example ```yaml -tools: - update_project_file: - kind: looker-update-project-file - source: looker-source - description: | - This tool modifies the content of an existing LookML file within a specified project. - - Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. - - Parameters: - - project_id (required): The unique ID of the LookML project. - - file_path (required): The exact path to the LookML file to modify within the project. - - content (required): The new, complete LookML content to overwrite the existing file. - - Output: - A confirmation message upon successful file modification. +kind: tools +name: update_project_file +type: looker-update-project-file +source: looker-source +description: | + This tool modifies the content of an existing LookML file within a specified project. + + Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first. + + Parameters: + - project_id (required): The unique ID of the LookML project. + - file_path (required): The exact path to the LookML file to modify within the project. + - content (required): The new, complete LookML content to overwrite the existing file. + + Output: + A confirmation message upon successful file modification. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "looker-update-project-file". | +| type | string | true | Must be "looker-update-project-file". | | source | string | true | Name of the source Looker instance. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mindsdb/_index.md b/docs/en/resources/tools/mindsdb/_index.md index 1a2f2cdff137..89d7828adbb7 100644 --- a/docs/en/resources/tools/mindsdb/_index.md +++ b/docs/en/resources/tools/mindsdb/_index.md @@ -117,20 +117,20 @@ federated database capabilities. Here's a complete working configuration that has been tested: ```yaml -sources: - my-pg-source: - kind: mindsdb - host: 127.0.0.1 - port: 47335 - database: files - user: mindsdb - -tools: - mindsdb-execute-sql: - kind: mindsdb-execute-sql - source: my-pg-source - description: | - Execute SQL queries directly on MindsDB database. - Use this tool to run any SQL statement against your MindsDB instance. - Example: SELECT * FROM my_table LIMIT 10 +kind: sources +name: my-pg-source +type: mindsdb +host: 127.0.0.1 +port: 47335 +database: files +user: mindsdb +--- +kind: tools +name: mindsdb-execute-sql +type: mindsdb-execute-sql +source: my-pg-source +description: | + Execute SQL queries directly on MindsDB database. + Use this tool to run any SQL statement against your MindsDB instance. + Example: SELECT * FROM my_table LIMIT 10 ``` diff --git a/docs/en/resources/tools/mindsdb/mindsdb-execute-sql.md b/docs/en/resources/tools/mindsdb/mindsdb-execute-sql.md index 1228caf83707..7b6da914d5dd 100644 --- a/docs/en/resources/tools/mindsdb/mindsdb-execute-sql.md +++ b/docs/en/resources/tools/mindsdb/mindsdb-execute-sql.md @@ -97,11 +97,11 @@ ORDER BY created_at DESC; ## Example ```yaml -tools: - execute_sql_tool: - kind: mindsdb-execute-sql - source: my-mindsdb-instance - description: Use this tool to execute SQL statements across multiple datasources and ML models. +kind: tools +name: execute_sql_tool +type: mindsdb-execute-sql +source: my-mindsdb-instance +description: Use this tool to execute SQL statements across multiple datasources and ML models. ``` ### Working Configuration Example @@ -109,28 +109,28 @@ tools: Here's a working configuration that has been tested: ```yaml -sources: - my-pg-source: - kind: mindsdb - host: 127.0.0.1 - port: 47335 - database: files - user: mindsdb - -tools: - mindsdb-execute-sql: - kind: mindsdb-execute-sql - source: my-pg-source - description: | - Execute SQL queries directly on MindsDB database. - Use this tool to run any SQL statement against your MindsDB instance. - Example: SELECT * FROM my_table LIMIT 10 +kind: sources +name: my-pg-source +type: mindsdb +host: 127.0.0.1 +port: 47335 +database: files +user: mindsdb +--- +kind: tools +name: mindsdb-execute-sql +type: mindsdb-execute-sql +source: my-pg-source +description: | + Execute SQL queries directly on MindsDB database. + Use this tool to run any SQL statement against your MindsDB instance. + Example: SELECT * FROM my_table LIMIT 10 ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "mindsdb-execute-sql". | +| type | string | true | Must be "mindsdb-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mindsdb/mindsdb-sql.md b/docs/en/resources/tools/mindsdb/mindsdb-sql.md index b0cfc189dc0f..44bea0d27c36 100644 --- a/docs/en/resources/tools/mindsdb/mindsdb-sql.md +++ b/docs/en/resources/tools/mindsdb/mindsdb-sql.md @@ -97,41 +97,41 @@ ORDER BY created_at DESC; > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: mindsdb-sql - source: my-mindsdb-instance - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: mindsdb-sql +source: my-mindsdb-instance +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -143,29 +143,29 @@ tools: > [templateParameters](../#template-parameters). ```yaml -tools: - list_table: - kind: mindsdb-sql - source: my-mindsdb-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: mindsdb-sql +source: my-mindsdb-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:------------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mindsdb-sql". | +| type | string | true | Must be "mindsdb-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/mongodb/mongodb-aggregate.md b/docs/en/resources/tools/mongodb/mongodb-aggregate.md index e37217ec77c9..43707e2a4e00 100644 --- a/docs/en/resources/tools/mongodb/mongodb-aggregate.md +++ b/docs/en/resources/tools/mongodb/mongodb-aggregate.md @@ -22,7 +22,7 @@ array of documents produced by the final stage of the pipeline. A `readOnly` flag can be set to `true` as a safety measure to ensure the pipeline does not contain any write stages (like `$out` or `$merge`). -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -32,45 +32,45 @@ Here is an example that calculates the average price and total count of products for each category, but only for products with an "active" status. ```yaml -tools: - get_category_stats: - kind: mongodb-aggregate - source: my-mongo-source - description: Calculates average price and count of products, grouped by category. - database: ecommerce - collection: products - readOnly: true - pipelinePayload: | - [ - { - "$match": { - "status": {{json .status_filter}} - } - }, - { - "$group": { - "_id": "$category", - "average_price": { "$avg": "$price" }, - "item_count": { "$sum": 1 } - } - }, - { - "$sort": { - "average_price": -1 - } - } - ] - pipelineParams: - - name: status_filter - type: string - description: The product status to filter by (e.g., "active"). +kind: tools +name: get_category_stats +type: mongodb-aggregate +source: my-mongo-source +description: Calculates average price and count of products, grouped by category. +database: ecommerce +collection: products +readOnly: true +pipelinePayload: | + [ + { + "$match": { + "status": {{json .status_filter}} + } + }, + { + "$group": { + "_id": "$category", + "average_price": { "$avg": "$price" }, + "item_count": { "$sum": 1 } + } + }, + { + "$sort": { + "average_price": -1 + } + } + ] +pipelineParams: + - name: status_filter + type: string + description: The product status to filter by (e.g., "active"). ``` ## Reference | **field** | **type** | **required** | **description** | |:----------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-aggregate`. | +| type | string | true | Must be `mongodb-aggregate`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-delete-many.md b/docs/en/resources/tools/mongodb/mongodb-delete-many.md index 9e35a7212468..b6ffcacc254d 100644 --- a/docs/en/resources/tools/mongodb/mongodb-delete-many.md +++ b/docs/en/resources/tools/mongodb/mongodb-delete-many.md @@ -17,7 +17,7 @@ The tool returns the total count of documents that were deleted. If the filter does not match any documents (i.e., the deleted count is 0), the tool will return an error. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -29,26 +29,26 @@ Here is an example that performs a cleanup task by deleting all products from the `inventory` collection that belong to a discontinued brand. ```yaml -tools: - retire_brand_products: - kind: mongodb-delete-many - source: my-mongo-source - description: Deletes all products from a specified discontinued brand. - database: ecommerce - collection: inventory - filterPayload: | - { "brand_name": {{json .brand_to_delete}} } - filterParams: - - name: brand_to_delete - type: string - description: The name of the discontinued brand whose products should be deleted. +kind: tools +name: retire_brand_products +type: mongodb-delete-many +source: my-mongo-source +description: Deletes all products from a specified discontinued brand. +database: ecommerce +collection: inventory +filterPayload: | + { "brand_name": {{json .brand_to_delete}} } +filterParams: + - name: brand_to_delete + type: string + description: The name of the discontinued brand whose products should be deleted. ``` ## Reference | **field** | **type** | **required** | **description** | |:--------------|:---------|:-------------|:--------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-delete-many`. | +| type | string | true | Must be `mongodb-delete-many`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-delete-one.md b/docs/en/resources/tools/mongodb/mongodb-delete-one.md index 0cede56c135f..3d9dc8dfa9c9 100644 --- a/docs/en/resources/tools/mongodb/mongodb-delete-one.md +++ b/docs/en/resources/tools/mongodb/mongodb-delete-one.md @@ -21,7 +21,7 @@ such as a user account or a single item from an inventory based on a unique ID. The tool returns the number of documents deleted, which will be either `1` if a document was found and deleted, or `0` if no matching document was found. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -33,26 +33,26 @@ Here is an example that deletes a specific user account from the `users` collection by matching their unique email address. This is a permanent action. ```yaml -tools: - delete_user_account: - kind: mongodb-delete-one - source: my-mongo-source - description: Permanently deletes a user account by their email address. - database: user_data - collection: users - filterPayload: | - { "email": {{json .email_address}} } - filterParams: - - name: email_address - type: string - description: The email of the user account to delete. +kind: tools +name: delete_user_account +type: mongodb-delete-one +source: my-mongo-source +description: Permanently deletes a user account by their email address. +database: user_data +collection: users +filterPayload: | + { "email": {{json .email_address}} } +filterParams: + - name: email_address + type: string + description: The email of the user account to delete. ``` ## Reference | **field** | **type** | **required** | **description** | |:--------------|:---------|:-------------|:-------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-delete-one`. | +| type | string | true | Must be `mongodb-delete-one`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-find-one.md b/docs/en/resources/tools/mongodb/mongodb-find-one.md index 395262d91ada..47f72cb289fb 100644 --- a/docs/en/resources/tools/mongodb/mongodb-find-one.md +++ b/docs/en/resources/tools/mongodb/mongodb-find-one.md @@ -18,7 +18,7 @@ returned. Otherwise, the selection is not guaranteed. The tool returns a single JSON object representing the document, wrapped in a JSON array. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -31,31 +31,31 @@ and returning their profile information, while excluding sensitive fields like the password hash. ```yaml -tools: - get_user_profile: - kind: mongodb-find-one - source: my-mongo-source - description: Retrieves a user's profile by their email address. - database: user_data - collection: profiles - filterPayload: | - { "email": {{json .email}} } - filterParams: - - name: email - type: string - description: The email address of the user to find. - projectPayload: | - { - "password_hash": 0, - "login_history": 0 - } +kind: tools +name: get_user_profile +type: mongodb-find-one +source: my-mongo-source +description: Retrieves a user's profile by their email address. +database: user_data +collection: profiles +filterPayload: | + { "email": {{json .email}} } +filterParams: + - name: email + type: string + description: The email address of the user to find. +projectPayload: | + { + "password_hash": 0, + "login_history": 0 + } ``` ## Reference | **field** | **type** | **required** | **description** | |:---------------|:---------|:-------------|:---------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-find-one`. | +| type | string | true | Must be `mongodb-find-one`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database to query. | diff --git a/docs/en/resources/tools/mongodb/mongodb-find.md b/docs/en/resources/tools/mongodb/mongodb-find.md index d927c737c1e6..c2ce3da0a3dd 100644 --- a/docs/en/resources/tools/mongodb/mongodb-find.md +++ b/docs/en/resources/tools/mongodb/mongodb-find.md @@ -18,7 +18,7 @@ results (**sorting**), and restricting the number of documents returned The tool returns a JSON array of the documents found. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -29,40 +29,40 @@ live in a specific city. The results are sorted by their last name, and only their first name, last name, and email are returned. ```yaml -tools: - find_local_customers: - kind: mongodb-find - source: my-mongo-source - description: Finds customers by city, sorted by last name. - database: crm - collection: customers - limit: 10 - filterPayload: | - { "address.city": {{json .city}} } - filterParams: - - name: city - type: string - description: The city to search for customers in. - projectPayload: | - { - "first_name": 1, - "last_name": 1, - "email": 1, - "_id": 0 - } - sortPayload: | - { "last_name": {{json .sort_order}} } - sortParams: - - name: sort_order - type: integer - description: The sort order (1 for ascending, -1 for descending). +kind: tools +name: find_local_customers +type: mongodb-find +source: my-mongo-source +description: Finds customers by city, sorted by last name. +database: crm +collection: customers +limit: 10 +filterPayload: | + { "address.city": {{json .city}} } +filterParams: + - name: city + type: string + description: The city to search for customers in. +projectPayload: | + { + "first_name": 1, + "last_name": 1, + "email": 1, + "_id": 0 + } +sortPayload: | + { "last_name": {{json .sort_order}} } +sortParams: + - name: sort_order + type: integer + description: The sort order (1 for ascending, -1 for descending). ``` ## Reference | **field** | **type** | **required** | **description** | |:---------------|:---------|:-------------|:----------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-find`. | +| type | string | true | Must be `mongodb-find`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database to query. | diff --git a/docs/en/resources/tools/mongodb/mongodb-insert-many.md b/docs/en/resources/tools/mongodb/mongodb-insert-many.md index cc6c38537536..cc6e0438d791 100644 --- a/docs/en/resources/tools/mongodb/mongodb-insert-many.md +++ b/docs/en/resources/tools/mongodb/mongodb-insert-many.md @@ -19,7 +19,7 @@ be a string containing a **JSON array of document objects**. Upon successful insertion, the tool returns a JSON array containing the unique `_id` of **each** new document that was created. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -30,14 +30,14 @@ This tool is compatible with the following source kind: Here is an example configuration for a tool that logs multiple events at once. ```yaml -tools: - log_batch_events: - kind: mongodb-insert-many - source: my-mongo-source - description: Inserts a batch of event logs into the database. - database: logging - collection: events - canonical: true +kind: tools +name: log_batch_events +type: mongodb-insert-many +source: my-mongo-source +description: Inserts a batch of event logs into the database. +database: logging +collection: events +canonical: true ``` An LLM would call this tool by providing an array of documents as a JSON string @@ -50,7 +50,7 @@ in the `data` parameter, like this: | **field** | **type** | **required** | **description** | |:------------|:---------|:-------------|:------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-insert-many`. | +| type | string | true | Must be `mongodb-insert-many`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-insert-one.md b/docs/en/resources/tools/mongodb/mongodb-insert-one.md index 7214f2b4d611..8545cc8e1021 100644 --- a/docs/en/resources/tools/mongodb/mongodb-insert-one.md +++ b/docs/en/resources/tools/mongodb/mongodb-insert-one.md @@ -17,7 +17,7 @@ This tool takes one required parameter named `data`, which must be a string containing the JSON object you want to insert. Upon successful insertion, the tool returns the unique `_id` of the newly created document. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -27,14 +27,14 @@ Here is an example configuration for a tool that adds a new user to a `users` collection. ```yaml -tools: - create_new_user: - kind: mongodb-insert-one - source: my-mongo-source - description: Creates a new user record in the database. - database: user_data - collection: users - canonical: false +kind: tools +name: create_new_user +type: mongodb-insert-one +source: my-mongo-source +description: Creates a new user record in the database. +database: user_data +collection: users +canonical: false ``` An LLM would call this tool by providing the document as a JSON string in the @@ -45,7 +45,7 @@ An LLM would call this tool by providing the document as a JSON string in the | **field** | **type** | **required** | **description** | |:------------|:---------|:-------------|:------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-insert-one`. | +| type | string | true | Must be `mongodb-insert-one`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-update-many.md b/docs/en/resources/tools/mongodb/mongodb-update-many.md index ef3b14436409..5fdb2e650ed2 100644 --- a/docs/en/resources/tools/mongodb/mongodb-update-many.md +++ b/docs/en/resources/tools/mongodb/mongodb-update-many.md @@ -17,7 +17,7 @@ MongoDB collection that match a given filter. It locates the documents using a The tool returns an array of three integers: `[ModifiedCount, UpsertedCount, MatchedCount]`. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -29,37 +29,37 @@ Here's an example configuration. This tool applies a discount to all items within a specific category and also marks them as being on sale. ```yaml -tools: - apply_category_discount: - kind: mongodb-update-many - source: my-mongo-source - description: Use this tool to apply a discount to all items in a given category. - database: products - collection: inventory - filterPayload: | - { "category": {{json .category_name}} } - filterParams: - - name: category_name - type: string - description: The category of items to update. - updatePayload: | - { - "$mul": { "price": {{json .discount_multiplier}} }, - "$set": { "on_sale": true } - } - updateParams: - - name: discount_multiplier - type: number - description: The multiplier to apply to the price (e.g., 0.8 for a 20% discount). - canonical: false - upsert: false +kind: tools +name: apply_category_discount +type: mongodb-update-many +source: my-mongo-source +description: Use this tool to apply a discount to all items in a given category. +database: products +collection: inventory +filterPayload: | + { "category": {{json .category_name}} } +filterParams: + - name: category_name + type: string + description: The category of items to update. +updatePayload: | + { + "$mul": { "price": {{json .discount_multiplier}} }, + "$set": { "on_sale": true } + } +updateParams: + - name: discount_multiplier + type: number + description: The multiplier to apply to the price (e.g., 0.8 for a 20% discount). +canonical: false +upsert: false ``` ## Reference | **field** | **type** | **required** | **description** | |:--------------|:---------|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-update-many`. | +| type | string | true | Must be `mongodb-update-many`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mongodb/mongodb-update-one.md b/docs/en/resources/tools/mongodb/mongodb-update-one.md index 063ea0b19288..e0bf51e3dd71 100644 --- a/docs/en/resources/tools/mongodb/mongodb-update-one.md +++ b/docs/en/resources/tools/mongodb/mongodb-update-one.md @@ -15,7 +15,7 @@ collection. It locates the document to be updated using a `filterPayload` and applies modifications defined in an `updatePayload`. If the filter matches multiple documents, only the first one found will be updated. -This tool is compatible with the following source kind: +This tool is compatible with the following source type: * [`mongodb`](../../sources/mongodb.md) @@ -29,37 +29,37 @@ collection where the `item` field matches a provided value. If no matching document is found, the `upsert: true` option will create a new one. ```yaml -tools: - update_inventory_item: - kind: mongodb-update-one - source: my-mongo-source - description: Use this tool to update an item's stock and status in the inventory. - database: products - collection: inventory - filterPayload: | - { "item": {{json .item_name}} } - filterParams: - - name: item_name - type: string - description: The name of the item to update. - updatePayload: | - { "$set": { "stock": {{json .new_stock}}, "status": {{json .new_status}} } } - updateParams: - - name: new_stock - type: integer - description: The new stock quantity. - - name: new_status - type: string - description: The new status of the item (e.g., "In Stock", "Backordered"). - canonical: false - upsert: true +kind: tools +name: update_inventory_item +type: mongodb-update-one +source: my-mongo-source +description: Use this tool to update an item's stock and status in the inventory. +database: products +collection: inventory +filterPayload: | + { "item": {{json .item_name}} } +filterParams: + - name: item_name + type: string + description: The name of the item to update. +updatePayload: | + { "$set": { "stock": {{json .new_stock}}, "status": {{json .new_status}} } } +updateParams: + - name: new_stock + type: integer + description: The new stock quantity. + - name: new_status + type: string + description: The new status of the item (e.g., "In Stock", "Backordered"). +canonical: false +upsert: true ``` ## Reference | **field** | **type** | **required** | **description** | |:--------------|:---------|:-------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be `mongodb-update-one`. | +| type | string | true | Must be `mongodb-update-one`. | | source | string | true | The name of the `mongodb` source to use. | | description | string | true | A description of the tool that is passed to the LLM. | | database | string | true | The name of the MongoDB database containing the collection. | diff --git a/docs/en/resources/tools/mssql/mssql-execute-sql.md b/docs/en/resources/tools/mssql/mssql-execute-sql.md index 4667dcf46b93..23bdbf664092 100644 --- a/docs/en/resources/tools/mssql/mssql-execute-sql.md +++ b/docs/en/resources/tools/mssql/mssql-execute-sql.md @@ -26,17 +26,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: mssql-execute-sql - source: my-mssql-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: mssql-execute-sql +source: my-mssql-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "mssql-execute-sql". | +| type | string | true | Must be "mssql-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mssql/mssql-list-tables.md b/docs/en/resources/tools/mssql/mssql-list-tables.md index 4a7fdf7a8d0d..d80c79cc17dd 100644 --- a/docs/en/resources/tools/mssql/mssql-list-tables.md +++ b/docs/en/resources/tools/mssql/mssql-list-tables.md @@ -32,17 +32,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - mssql_list_tables: - kind: mssql-list-tables - source: mssql-source - description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed. +kind: tools +name: mssql_list_tables +type: mssql-list-tables +source: mssql-source +description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "mssql-list-tables". | +| type | string | true | Must be "mssql-list-tables". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/mssql/mssql-sql.md b/docs/en/resources/tools/mssql/mssql-sql.md index e4c63184c2cd..c5d212f0967d 100644 --- a/docs/en/resources/tools/mssql/mssql-sql.md +++ b/docs/en/resources/tools/mssql/mssql-sql.md @@ -36,41 +36,41 @@ db.QueryContext(ctx, `select * from t where ID = @ID and Name = @p2;`, sql.Named > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: mssql-sql - source: my-instance - statement: | - SELECT * FROM flights - WHERE airline = @airline - AND flight_number = @flight_number - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: mssql-sql +source: my-instance +statement: | + SELECT * FROM flights + WHERE airline = @airline + AND flight_number = @flight_number + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -82,29 +82,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: mssql-sql - source: my-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: mssql-sql +source: my-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mssql-sql". | +| type | string | true | Must be "mssql-sql". | | source | string | true | Name of the source the T-SQL statement should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute. | diff --git a/docs/en/resources/tools/mysql/mysql-execute-sql.md b/docs/en/resources/tools/mysql/mysql-execute-sql.md index ff68b065169b..dce807047131 100644 --- a/docs/en/resources/tools/mysql/mysql-execute-sql.md +++ b/docs/en/resources/tools/mysql/mysql-execute-sql.md @@ -26,17 +26,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: mysql-execute-sql - source: my-mysql-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: mysql-execute-sql +source: my-mysql-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mysql-execute-sql". | +| type | string | true | Must be "mysql-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mysql/mysql-get-query-plan.md b/docs/en/resources/tools/mysql/mysql-get-query-plan.md index d77b81e09759..b3e259b5afb4 100644 --- a/docs/en/resources/tools/mysql/mysql-get-query-plan.md +++ b/docs/en/resources/tools/mysql/mysql-get-query-plan.md @@ -23,17 +23,17 @@ statement against the `source`. ## Example ```yaml -tools: - get_query_plan_tool: - kind: mysql-get-query-plan - source: my-mysql-instance - description: Use this tool to get the execution plan for a sql statement. +kind: tools +name: get_query_plan_tool +type: mysql-get-query-plan +source: my-mysql-instance +description: Use this tool to get the execution plan for a sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mysql-get-query-plan". | +| type | string | true | Must be "mysql-get-query-plan". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mysql/mysql-list-active-queries.md b/docs/en/resources/tools/mysql/mysql-list-active-queries.md index f7a2721abafe..7f0ba3c0fdc0 100644 --- a/docs/en/resources/tools/mysql/mysql-list-active-queries.md +++ b/docs/en/resources/tools/mysql/mysql-list-active-queries.md @@ -27,11 +27,11 @@ This tool takes 2 optional input parameters: ## Example ```yaml -tools: - list_active_queries: - kind: mysql-list-active-queries - source: my-mysql-instance - description: Lists top N (default 10) ongoing queries from processlist and innodb_trx, ordered by execution time in descending order. Returns detailed information of those queries in json format, including process id, query, transaction duration, transaction wait duration, process time, transaction state, process state, username with host, transaction rows locked, transaction rows modified, and db schema. +kind: tools +name: list_active_queries +type: mysql-list-active-queries +source: my-mysql-instance +description: Lists top N (default 10) ongoing queries from processlist and innodb_trx, ordered by execution time in descending order. Returns detailed information of those queries in json format, including process id, query, transaction duration, transaction wait duration, process time, transaction state, process state, username with host, transaction rows locked, transaction rows modified, and db schema. ``` The response is a json array with the following fields: @@ -57,6 +57,6 @@ The response is a json array with the following fields: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "mysql-list-active-queries". | +| type | string | true | Must be "mysql-list-active-queries". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mysql/mysql-list-table-fragmentation.md b/docs/en/resources/tools/mysql/mysql-list-table-fragmentation.md index 1af1308a71fa..3e0ce0c5a9ee 100644 --- a/docs/en/resources/tools/mysql/mysql-list-table-fragmentation.md +++ b/docs/en/resources/tools/mysql/mysql-list-table-fragmentation.md @@ -34,11 +34,11 @@ This tool takes 4 optional input parameters: ## Example ```yaml -tools: - list_table_fragmentation: - kind: mysql-list-table-fragmentation - source: my-mysql-instance - description: List table fragmentation in MySQL, by calculating the size of the data and index files and free space allocated to each table. The query calculates fragmentation percentage which represents the proportion of free space relative to the total data and index size. Storage can be reclaimed for tables with high fragmentation using OPTIMIZE TABLE. +kind: tools +name: list_table_fragmentation +type: mysql-list-table-fragmentation +source: my-mysql-instance +description: List table fragmentation in MySQL, by calculating the size of the data and index files and free space allocated to each table. The query calculates fragmentation percentage which represents the proportion of free space relative to the total data and index size. Storage can be reclaimed for tables with high fragmentation using OPTIMIZE TABLE. ``` The response is a json array with the following fields: @@ -58,6 +58,6 @@ The response is a json array with the following fields: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "mysql-list-table-fragmentation". | +| type | string | true | Must be "mysql-list-table-fragmentation". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mysql/mysql-list-tables-missing-unique-indexes.md b/docs/en/resources/tools/mysql/mysql-list-tables-missing-unique-indexes.md index 087860141afa..7c1c08296a23 100644 --- a/docs/en/resources/tools/mysql/mysql-list-tables-missing-unique-indexes.md +++ b/docs/en/resources/tools/mysql/mysql-list-tables-missing-unique-indexes.md @@ -27,11 +27,11 @@ parameters: ## Example ```yaml -tools: - list_tables_missing_unique_indexes: - kind: mysql-list-tables-missing-unique-indexes - source: my-mysql-instance - description: Find tables that do not have primary or unique key constraint. A primary key or unique key is the only mechanism that guaranttes a row is unique. Without them, the database-level protection against data integrity issues will be missing. +kind: tools +name: list_tables_missing_unique_indexes +type: mysql-list-tables-missing-unique-indexes +source: my-mysql-instance +description: Find tables that do not have primary or unique key constraint. A primary key or unique key is the only mechanism that guaranttes a row is unique. Without them, the database-level protection against data integrity issues will be missing. ``` The response is a json array with the following fields: @@ -47,6 +47,6 @@ The response is a json array with the following fields: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "mysql-list-active-queries". | +| type | string | true | Must be "mysql-list-active-queries". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/mysql/mysql-list-tables.md b/docs/en/resources/tools/mysql/mysql-list-tables.md index f07eef7c6837..62da629c3b6f 100644 --- a/docs/en/resources/tools/mysql/mysql-list-tables.md +++ b/docs/en/resources/tools/mysql/mysql-list-tables.md @@ -33,17 +33,17 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - mysql_list_tables: - kind: mysql-list-tables - source: mysql-source - description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed. +kind: tools +name: mysql_list_tables +type: mysql-list-tables +source: mysql-source +description: Use this tool to retrieve schema information for all or specified tables. Output format can be simple (only table names) or detailed. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "mysql-list-tables". | +| type | string | true | Must be "mysql-list-tables". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/mysql/mysql-sql.md b/docs/en/resources/tools/mysql/mysql-sql.md index 56850ba0b26f..9d534a6c03aa 100644 --- a/docs/en/resources/tools/mysql/mysql-sql.md +++ b/docs/en/resources/tools/mysql/mysql-sql.md @@ -30,41 +30,41 @@ and expects parameters in the SQL query to be in the form of placeholders `?`. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: mysql-sql - source: my-mysql-instance - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: mysql-sql +source: my-mysql-instance +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -76,29 +76,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: mysql-sql - source: my-mysql-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: mysql-sql +source: my-mysql-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:------------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "mysql-sql". | +| type | string | true | Must be "mysql-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/neo4j/neo4j-cypher.md b/docs/en/resources/tools/neo4j/neo4j-cypher.md index 1086f1369332..f058c4eca62f 100644 --- a/docs/en/resources/tools/neo4j/neo4j-cypher.md +++ b/docs/en/resources/tools/neo4j/neo4j-cypher.md @@ -31,46 +31,46 @@ their name: e.g. `$id`. ## Example ```yaml -tools: - search_movies_by_actor: - kind: neo4j-cypher - source: my-neo4j-movies-instance - statement: | - MATCH (m:Movie)<-[:ACTED_IN]-(p:Person) - WHERE p.name = $name AND m.year > $year - RETURN m.title, m.year - LIMIT 10 - description: | - Use this tool to get a list of movies for a specific actor and a given minimum release year. - Takes a full actor name, e.g. "Tom Hanks" and a year e.g 1993 and returns a list of movie titles and release years. - Do NOT use this tool with a movie title. Do NOT guess an actor name, Do NOT guess a year. - A actor name is a fully qualified name with first and last name separated by a space. - For example, if given "Hanks, Tom" the actor name is "Tom Hanks". - If the tool returns more than one option choose the most recent movies. - Example: - {{ - "name": "Meg Ryan", - "year": 1993 - }} - Example: - {{ - "name": "Clint Eastwood", - "year": 2000 - }} - parameters: - - name: name - type: string - description: Full actor name, "firstname lastname" - - name: year - type: integer - description: 4 digit number starting in 1900 up to the current year +kind: tools +name: search_movies_by_actor +type: neo4j-cypher +source: my-neo4j-movies-instance +statement: | + MATCH (m:Movie)<-[:ACTED_IN]-(p:Person) + WHERE p.name = $name AND m.year > $year + RETURN m.title, m.year + LIMIT 10 +description: | + Use this tool to get a list of movies for a specific actor and a given minimum release year. + Takes a full actor name, e.g. "Tom Hanks" and a year e.g 1993 and returns a list of movie titles and release years. + Do NOT use this tool with a movie title. Do NOT guess an actor name, Do NOT guess a year. + A actor name is a fully qualified name with first and last name separated by a space. + For example, if given "Hanks, Tom" the actor name is "Tom Hanks". + If the tool returns more than one option choose the most recent movies. + Example: + {{ + "name": "Meg Ryan", + "year": 1993 + }} + Example: + {{ + "name": "Clint Eastwood", + "year": 2000 + }} +parameters: + - name: name + type: string + description: Full actor name, "firstname lastname" + - name: year + type: integer + description: 4 digit number starting in 1900 up to the current year ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:---------------------------------------:|:------------:|----------------------------------------------------------------------------------------------| -| kind | string | true | Must be "neo4j-cypher". | +| type | string | true | Must be "neo4j-cypher". | | source | string | true | Name of the source the Cypher query should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | Cypher statement to execute | diff --git a/docs/en/resources/tools/neo4j/neo4j-execute-cypher.md b/docs/en/resources/tools/neo4j/neo4j-execute-cypher.md index 642f4234cf6a..e3828693d806 100644 --- a/docs/en/resources/tools/neo4j/neo4j-execute-cypher.md +++ b/docs/en/resources/tools/neo4j/neo4j-execute-cypher.md @@ -37,26 +37,26 @@ parameter to validate a query without executing it. ## Example ```yaml -tools: - query_neo4j: - kind: neo4j-execute-cypher - source: my-neo4j-prod-db - readOnly: true - description: | - Use this tool to execute a Cypher query against the production database. - Only read-only queries are allowed. - Takes a single 'cypher' parameter containing the full query string. - Example: - {{ - "cypher": "MATCH (m:Movie {title: 'The Matrix'}) RETURN m.released" - }} +kind: tools +name: query_neo4j +type: neo4j-execute-cypher +source: my-neo4j-prod-db +readOnly: true +description: | + Use this tool to execute a Cypher query against the production database. + Only read-only queries are allowed. + Takes a single 'cypher' parameter containing the full query string. + Example: + {{ + "cypher": "MATCH (m:Movie {title: 'The Matrix'}) RETURN m.released" + }} ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "neo4j-cypher". | +| type | string | true | Must be "neo4j-cypher". | | source | string | true | Name of the source the Cypher query should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | readOnly | boolean | false | If set to `true`, the tool will reject any write operations in the Cypher query. Default is `false`. | diff --git a/docs/en/resources/tools/neo4j/neo4j-schema.md b/docs/en/resources/tools/neo4j/neo4j-schema.md index aee380ebc55f..31c3bcb81abf 100644 --- a/docs/en/resources/tools/neo4j/neo4j-schema.md +++ b/docs/en/resources/tools/neo4j/neo4j-schema.md @@ -28,24 +28,24 @@ tool is compatible with a `neo4j` source and takes no parameters. ## Example ```yaml -tools: - get_movie_db_schema: - kind: neo4j-schema - source: my-neo4j-movies-instance - description: | - Use this tool to get the full schema of the movie database. - This provides information on all available node labels (like Movie, Person), - relationships (like ACTED_IN), and the properties on each. - This tool takes no parameters. - # Optional configuration to cache the schema for 2 hours - cacheExpireMinutes: 120 +kind: tools +name: get_movie_db_schema +type: neo4j-schema +source: my-neo4j-movies-instance +description: | + Use this tool to get the full schema of the movie database. + This provides information on all available node labels (like Movie, Person), + relationships (like ACTED_IN), and the properties on each. + This tool takes no parameters. +# Optional configuration to cache the schema for 2 hours +cacheExpireMinutes: 120 ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------:|:------------:|---------------------------------------------------------| -| kind | string | true | Must be `neo4j-schema`. | +| type | string | true | Must be `neo4j-schema`. | | source | string | true | Name of the source the schema should be extracted from. | | description | string | true | Description of the tool that is passed to the LLM. | | cacheExpireMinutes | integer | false | Cache expiration time in minutes. Defaults to 60. | diff --git a/docs/en/resources/tools/oceanbase/oceanbase-execute-sql.md b/docs/en/resources/tools/oceanbase/oceanbase-execute-sql.md index 36432b2e8b71..fe43ff54b9f2 100644 --- a/docs/en/resources/tools/oceanbase/oceanbase-execute-sql.md +++ b/docs/en/resources/tools/oceanbase/oceanbase-execute-sql.md @@ -24,17 +24,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: oceanbase-execute-sql - source: my-oceanbase-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: oceanbase-execute-sql +source: my-oceanbase-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "oceanbase-execute-sql". | +| type | string | true | Must be "oceanbase-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/oceanbase/oceanbase-sql.md b/docs/en/resources/tools/oceanbase/oceanbase-sql.md index ee33d3cd7c33..aafdadc3d6f8 100644 --- a/docs/en/resources/tools/oceanbase/oceanbase-sql.md +++ b/docs/en/resources/tools/oceanbase/oceanbase-sql.md @@ -29,31 +29,31 @@ form of placeholders `?`. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: oceanbase-sql - source: my-oceanbase-instance - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: oceanbase-sql +source: my-oceanbase-instance +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -64,64 +64,64 @@ tools: > recommended for performance and safety reasons. ```yaml -tools: - list_table: - kind: oceanbase-sql - source: my-oceanbase-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: oceanbase-sql +source: my-oceanbase-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ### Example with Array Parameters ```yaml -tools: - search_flights_by_ids: - kind: oceanbase-sql - source: my-oceanbase-instance - statement: | - SELECT * FROM flights - WHERE id IN (?) - AND status IN (?) - description: | - Use this tool to get information for multiple flights by their IDs and statuses. - Example: - {{ - "flight_ids": [1, 2, 3], - "statuses": ["active", "scheduled"] - }} - parameters: - - name: flight_ids - type: array - description: List of flight IDs to search for - items: - name: flight_id - type: integer - description: Individual flight ID - - name: statuses - type: array - description: List of flight statuses to filter by - items: - name: status - type: string - description: Individual flight status +kind: tools +name: search_flights_by_ids +type: oceanbase-sql +source: my-oceanbase-instance +statement: | + SELECT * FROM flights + WHERE id IN (?) + AND status IN (?) +description: | + Use this tool to get information for multiple flights by their IDs and statuses. + Example: + {{ + "flight_ids": [1, 2, 3], + "statuses": ["active", "scheduled"] + }} +parameters: + - name: flight_ids + type: array + description: List of flight IDs to search for + items: + name: flight_id + type: integer + description: Individual flight ID + - name: statuses + type: array + description: List of flight statuses to filter by + items: + name: status + type: string + description: Individual flight status ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "oceanbase-sql". | +| type | string | true | Must be "oceanbase-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/oracle/oracle-execute-sql.md b/docs/en/resources/tools/oracle/oracle-execute-sql.md index c66cce2b8cec..cbfd79037bd3 100644 --- a/docs/en/resources/tools/oracle/oracle-execute-sql.md +++ b/docs/en/resources/tools/oracle/oracle-execute-sql.md @@ -24,8 +24,9 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: oracle-execute-sql - source: my-oracle-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: oracle-execute-sql +source: my-oracle-instance +description: Use this tool to execute sql statement. +``` diff --git a/docs/en/resources/tools/oracle/oracle-sql.md b/docs/en/resources/tools/oracle/oracle-sql.md index 045031f60c31..49d665be360d 100644 --- a/docs/en/resources/tools/oracle/oracle-sql.md +++ b/docs/en/resources/tools/oracle/oracle-sql.md @@ -29,29 +29,29 @@ to be in the native Oracle format (e.g., `:1`, `:2`). > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: oracle-sql - source: my-oracle-instance - statement: | - SELECT * FROM flights - WHERE airline = :1 - AND flight_number = :2 - FETCH FIRST 10 ROWS ONLY - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: oracle-sql +source: my-oracle-instance +statement: | + SELECT * FROM flights + WHERE airline = :1 + AND flight_number = :2 + FETCH FIRST 10 ROWS ONLY +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` diff --git a/docs/en/resources/tools/postgres/postgres-database-overview.md b/docs/en/resources/tools/postgres/postgres-database-overview.md index 485a8625fb8e..1dcb23dc45dd 100644 --- a/docs/en/resources/tools/postgres/postgres-database-overview.md +++ b/docs/en/resources/tools/postgres/postgres-database-overview.md @@ -23,12 +23,12 @@ This tool does not take any input parameters. ## Example ```yaml -tools: - database_overview: - kind: postgres-database-overview - source: cloudsql-pg-source - description: | - fetches the current state of the PostgreSQL server. It returns the postgres version, whether it's a replica, uptime duration, maximum connection limit, number of current connections, number of active connections and the percentage of connections in use. +kind: tools +name: database_overview +type: postgres-database-overview +source: cloudsql-pg-source +description: | + fetches the current state of the PostgreSQL server. It returns the postgres version, whether it's a replica, uptime duration, maximum connection limit, number of current connections, number of active connections and the percentage of connections in use. ``` The response is a JSON object with the following elements: @@ -49,6 +49,6 @@ The response is a JSON object with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-database-overview". | +| type | string | true | Must be "postgres-database-overview". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-execute-sql.md b/docs/en/resources/tools/postgres/postgres-execute-sql.md index 6670efcb0b98..07a38474050a 100644 --- a/docs/en/resources/tools/postgres/postgres-execute-sql.md +++ b/docs/en/resources/tools/postgres/postgres-execute-sql.md @@ -27,17 +27,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: postgres-execute-sql - source: my-pg-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: postgres-execute-sql +source: my-pg-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "postgres-execute-sql". | +| type | string | true | Must be "postgres-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-get-column-cardinality.md b/docs/en/resources/tools/postgres/postgres-get-column-cardinality.md index 2563ead4f113..4cd778d19da9 100644 --- a/docs/en/resources/tools/postgres/postgres-get-column-cardinality.md +++ b/docs/en/resources/tools/postgres/postgres-get-column-cardinality.md @@ -30,11 +30,11 @@ the following input parameters: ## Example ```yaml -tools: - get_column_cardinality: - kind: postgres-get-column-cardinality - source: postgres-source - description: Estimates the number of unique values (cardinality) quickly for one or all columns in a specific PostgreSQL table by using the database's internal statistics, returning the results in descending order of estimated cardinality. Please run ANALYZE on the table before using this tool to get accurate results. The tool returns the column_name and the estimated_cardinality. If the column_name is not provided, the tool returns all columns along with their estimated cardinality. +kind: tools +name: get_column_cardinality +type: postgres-get-column-cardinality +source: postgres-source +description: Estimates the number of unique values (cardinality) quickly for one or all columns in a specific PostgreSQL table by using the database's internal statistics, returning the results in descending order of estimated cardinality. Please run ANALYZE on the table before using this tool to get accurate results. The tool returns the column_name and the estimated_cardinality. If the column_name is not provided, the tool returns all columns along with their estimated cardinality. ``` The response is a json array with the following elements: @@ -58,6 +58,6 @@ to estimate cardinality. | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-get-column-cardinality". | +| type | string | true | Must be "postgres-get-column-cardinality". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-list-active-queries.md b/docs/en/resources/tools/postgres/postgres-list-active-queries.md index 2184d96f7028..2c533b15bac4 100644 --- a/docs/en/resources/tools/postgres/postgres-list-active-queries.md +++ b/docs/en/resources/tools/postgres/postgres-list-active-queries.md @@ -33,11 +33,11 @@ active queries. The tool takes the following input parameters: ## Example ```yaml -tools: - list_active_queries: - kind: postgres-list-active-queries - source: postgres-source - description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text. +kind: tools +name: list_active_queries +type: postgres-list-active-queries +source: postgres-source +description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text. ``` The response is a json array with the following elements: @@ -64,6 +64,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "postgres-list-active-queries". | +| type | string | true | Must be "postgres-list-active-queries". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-list-available-extensions.md b/docs/en/resources/tools/postgres/postgres-list-available-extensions.md index dc823c78a575..cc2845baa334 100644 --- a/docs/en/resources/tools/postgres/postgres-list-available-extensions.md +++ b/docs/en/resources/tools/postgres/postgres-list-available-extensions.md @@ -26,11 +26,11 @@ not support any input parameter. ## Example ```yaml -tools: - list_available_extensions: - kind: postgres-list-available-extensions - source: postgres-source - description: Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description. +kind: tools +name: list_available_extensions +type: postgres-list-available-extensions +source: postgres-source +description: Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description. ``` ## Reference diff --git a/docs/en/resources/tools/postgres/postgres-list-database-stats.md b/docs/en/resources/tools/postgres/postgres-list-database-stats.md index 01537bcfa756..7d9e3f57aaf1 100644 --- a/docs/en/resources/tools/postgres/postgres-list-database-stats.md +++ b/docs/en/resources/tools/postgres/postgres-list-database-stats.md @@ -30,31 +30,31 @@ takes the following input parameters: ## Example ```yaml -tools: - list_database_stats: - kind: postgres-list-database-stats - source: postgres-source - description: | - Lists the key performance and activity statistics for each PostgreSQL - database in the instance, offering insights into cache efficiency, - transaction throughput row-level activity, temporary file usage, and - contention. It returns: the database name, whether the database is - connectable, database owner, default tablespace name, the percentage of - data blocks found in the buffer cache rather than being read from disk - (a higher value indicates better cache performance), the total number of - disk blocks read from disk, the total number of times disk blocks were - found already in the cache; the total number of committed transactions, - the total number of rolled back transactions, the percentage of rolled - back transactions compared to the total number of completed - transactions, the total number of rows returned by queries, the total - number of live rows fetched by scans, the total number of rows inserted, - the total number of rows updated, the total number of rows deleted, the - number of temporary files created by queries, the total size of - temporary files used by queries in bytes, the number of query - cancellations due to conflicts with recovery, the number of deadlocks - detected, the current number of active backend connections, the - timestamp when the database statistics were last reset, and the total - database size in bytes. +kind: tools +name: list_database_stats +type: postgres-list-database-stats +source: postgres-source +description: | + Lists the key performance and activity statistics for each PostgreSQL + database in the instance, offering insights into cache efficiency, + transaction throughput row-level activity, temporary file usage, and + contention. It returns: the database name, whether the database is + connectable, database owner, default tablespace name, the percentage of + data blocks found in the buffer cache rather than being read from disk + (a higher value indicates better cache performance), the total number of + disk blocks read from disk, the total number of times disk blocks were + found already in the cache; the total number of committed transactions, + the total number of rolled back transactions, the percentage of rolled + back transactions compared to the total number of completed + transactions, the total number of rows returned by queries, the total + number of live rows fetched by scans, the total number of rows inserted, + the total number of rows updated, the total number of rows deleted, the + number of temporary files created by queries, the total size of + temporary files used by queries in bytes, the number of query + cancellations due to conflicts with recovery, the number of deadlocks + detected, the current number of active backend connections, the + timestamp when the database statistics were last reset, and the total + database size in bytes. ``` The response is a json array with the following elements: @@ -90,6 +90,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-database-stats". | +| type | string | true | Must be "postgres-list-database-stats". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-indexes.md b/docs/en/resources/tools/postgres/postgres-list-indexes.md index f528ae97ecf4..590b09bb3315 100644 --- a/docs/en/resources/tools/postgres/postgres-list-indexes.md +++ b/docs/en/resources/tools/postgres/postgres-list-indexes.md @@ -30,18 +30,18 @@ takes the following input parameters: ## Example ```yaml -tools: - list_indexes: - kind: postgres-list-indexes - source: postgres-source - description: | - Lists available user indexes in the database, excluding system schemas (pg_catalog, - information_schema). For each index, the following properties are returned: - schema name, table name, index name, index type (access method), a boolean - indicating if it's a unique index, a boolean indicating if it's for a primary key, - the index definition, index size in bytes, the number of index scans, the number of - index tuples read, the number of table tuples fetched via index scans, and a boolean - indicating if the index has been used at least once. +kind: tools +name: list_indexes +type: postgres-list-indexes +source: postgres-source +description: | + Lists available user indexes in the database, excluding system schemas (pg_catalog, + information_schema). For each index, the following properties are returned: + schema name, table name, index name, index type (access method), a boolean + indicating if it's a unique index, a boolean indicating if it's for a primary key, + the index definition, index size in bytes, the number of index scans, the number of + index tuples read, the number of table tuples fetched via index scans, and a boolean + indicating if the index has been used at least once. ``` The response is a json array with the following elements: @@ -67,6 +67,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-indexes". | +| type | string | true | Must be "postgres-list-indexes". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-installed-extensions.md b/docs/en/resources/tools/postgres/postgres-list-installed-extensions.md index d3ff4eb26f16..afda5031bc7c 100644 --- a/docs/en/resources/tools/postgres/postgres-list-installed-extensions.md +++ b/docs/en/resources/tools/postgres/postgres-list-installed-extensions.md @@ -26,17 +26,17 @@ support any input parameter. ## Example ```yaml -tools: - list_installed_extensions: - kind: postgres-list-installed-extensions - source: postgres-source - description: List all installed PostgreSQL extensions with their name, version, schema, owner, and description. +kind: tools +name: list_installed_extensions +type: postgres-list-installed-extensions +source: postgres-source +description: List all installed PostgreSQL extensions with their name, version, schema, owner, and description. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "postgres-list-active-queries". | +| type | string | true | Must be "postgres-list-active-queries". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-list-locks.md b/docs/en/resources/tools/postgres/postgres-list-locks.md index a0d60e93d9ad..4b7b8c6bb2de 100644 --- a/docs/en/resources/tools/postgres/postgres-list-locks.md +++ b/docs/en/resources/tools/postgres/postgres-list-locks.md @@ -49,11 +49,11 @@ GROUP BY ## Example ```yaml -tools: - list_locks: - kind: postgres-list-locks - source: postgres-source - description: "Lists active locks with associated process and query information." +kind: tools +name: list_locks +type: postgres-list-locks +source: postgres-source +description: "Lists active locks with associated process and query information." ``` Example response element (aggregated per process): diff --git a/docs/en/resources/tools/postgres/postgres-list-pg-settings.md b/docs/en/resources/tools/postgres/postgres-list-pg-settings.md index 23d5e28e9227..895dbebf218a 100644 --- a/docs/en/resources/tools/postgres/postgres-list-pg-settings.md +++ b/docs/en/resources/tools/postgres/postgres-list-pg-settings.md @@ -25,16 +25,16 @@ takes the following input parameters: ## Example ```yaml -tools: - list_indexes: - kind: postgres-list-pg-settings - source: postgres-source - description: | - Lists configuration parameters for the postgres server ordered lexicographically, - with a default limit of 50 rows. It returns the parameter name, its current setting, - unit of measurement, a short description, the source of the current setting (e.g., - default, configuration file, session), and whether a restart is required when the - parameter value is changed." +kind: tools +name: list_indexes +type: postgres-list-pg-settings +source: postgres-source +description: | + Lists configuration parameters for the postgres server ordered lexicographically, + with a default limit of 50 rows. It returns the parameter name, its current setting, + unit of measurement, a short description, the source of the current setting (e.g., + default, configuration file, session), and whether a restart is required when the + parameter value is changed." ``` The response is a json array with the following elements: @@ -54,6 +54,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-pg-settings". | +| type | string | true | Must be "postgres-list-pg-settings". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-publication-tables.md b/docs/en/resources/tools/postgres/postgres-list-publication-tables.md index a437d11783b7..981402aa157a 100644 --- a/docs/en/resources/tools/postgres/postgres-list-publication-tables.md +++ b/docs/en/resources/tools/postgres/postgres-list-publication-tables.md @@ -28,18 +28,18 @@ of tables) as part of the logical replication feature. The tool takes the follow ## Example ```yaml -tools: - list_indexes: - kind: postgres-list-publication-tables - source: postgres-source - description: | - Lists all tables that are explicitly part of a publication in the database. - Tables that are part of a publication via 'FOR ALL TABLES' are not included, - unless they are also explicitly added to the publication. - Returns the publication name, schema name, and table name, along with - definition details indicating if it publishes all tables, whether it - replicates inserts, updates, deletes, or truncates, and the publication - owner. +kind: tools +name: list_indexes +type: postgres-list-publication-tables +source: postgres-source +description: | + Lists all tables that are explicitly part of a publication in the database. + Tables that are part of a publication via 'FOR ALL TABLES' are not included, + unless they are also explicitly added to the publication. + Returns the publication name, schema name, and table name, along with + definition details indicating if it publishes all tables, whether it + replicates inserts, updates, deletes, or truncates, and the publication + owner. ``` The response is a JSON array with the following elements: @@ -61,6 +61,6 @@ The response is a JSON array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-publication-tables". | +| type | string | true | Must be "postgres-list-publication-tables". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-query-stats.md b/docs/en/resources/tools/postgres/postgres-list-query-stats.md index d6bfc9cb5762..b5120cf357ab 100644 --- a/docs/en/resources/tools/postgres/postgres-list-query-stats.md +++ b/docs/en/resources/tools/postgres/postgres-list-query-stats.md @@ -29,11 +29,11 @@ total execution time in descending order. The tool takes the following input par ## Example ```yaml -tools: - list_query_stats: - kind: postgres-list-query-stats - source: postgres-source - description: List query statistics from pg_stat_statements, showing performance metrics for queries including execution counts, timing information, and resource usage. Results are ordered by total execution time descending. +kind: tools +name: list_query_stats +type: postgres-list-query-stats +source: postgres-source +description: List query statistics from pg_stat_statements, showing performance metrics for queries including execution counts, timing information, and resource usage. Results are ordered by total execution time descending. ``` The response is a json array with the following elements: @@ -66,6 +66,6 @@ identifying slow queries and understanding query performance patterns. | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-query-stats". | +| type | string | true | Must be "postgres-list-query-stats". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-list-roles.md b/docs/en/resources/tools/postgres/postgres-list-roles.md index d3de6abdfbb8..abfaefc84edf 100644 --- a/docs/en/resources/tools/postgres/postgres-list-roles.md +++ b/docs/en/resources/tools/postgres/postgres-list-roles.md @@ -26,19 +26,19 @@ takes the following input parameters: ## Example ```yaml -tools: - list_indexes: - kind: postgres-list-roles - source: postgres-source - description: | - Lists all the user-created roles in the instance . It returns the role name, - Object ID, the maximum number of concurrent connections the role can make, - along with boolean indicators for: superuser status, privilege inheritance - from member roles, ability to create roles, ability to create databases, - ability to log in, replication privilege, and the ability to bypass - row-level security, the password expiration timestamp, a list of direct - members belonging to this role, and a list of other roles/groups that this - role is a member of. +kind: tools +name: list_indexes +type: postgres-list-roles +source: postgres-source +description: | + Lists all the user-created roles in the instance . It returns the role name, + Object ID, the maximum number of concurrent connections the role can make, + along with boolean indicators for: superuser status, privilege inheritance + from member roles, ability to create roles, ability to create databases, + ability to log in, replication privilege, and the ability to bypass + row-level security, the password expiration timestamp, a list of direct + members belonging to this role, and a list of other roles/groups that this + role is a member of. ``` The response is a json array with the following elements: @@ -65,6 +65,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-roles". | +| type | string | true | Must be "postgres-list-roles". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-schemas.md b/docs/en/resources/tools/postgres/postgres-list-schemas.md index 6c0eb9e82a00..5933085fe13e 100644 --- a/docs/en/resources/tools/postgres/postgres-list-schemas.md +++ b/docs/en/resources/tools/postgres/postgres-list-schemas.md @@ -28,11 +28,11 @@ tool takes the following input parameters: ## Example ```yaml -tools: - list_schemas: - kind: postgres-list-schemas - source: postgres-source - description: "Lists all schemas in the database ordered by schema name and excluding system and temporary schemas. It returns the schema name, schema owner, grants, number of functions, number of tables and number of views within each schema." +kind: tools +name: list_schemas +type: postgres-list-schemas +source: postgres-source +description: "Lists all schemas in the database ordered by schema name and excluding system and temporary schemas. It returns the schema name, schema owner, grants, number of functions, number of tables and number of views within each schema." ``` The response is a json array with the following elements: @@ -52,6 +52,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "postgres-list-schemas". | +| type | string | true | Must be "postgres-list-schemas". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/postgres/postgres-list-sequences.md b/docs/en/resources/tools/postgres/postgres-list-sequences.md index e51915525ade..3f5efe853b19 100644 --- a/docs/en/resources/tools/postgres/postgres-list-sequences.md +++ b/docs/en/resources/tools/postgres/postgres-list-sequences.md @@ -29,16 +29,16 @@ The tool takes the following input parameters: ## Example ```yaml -tools: - list_indexes: - kind: postgres-list-sequences - source: postgres-source - description: | - Lists all the sequences in the database ordered by sequence name. - Returns sequence name, schema name, sequence owner, data type of the - sequence, starting value, minimum value, maximum value of the sequence, - the value by which the sequence is incremented, and the last value - generated by generated by the sequence in the current session. +kind: tools +name: list_indexes +type: postgres-list-sequences +source: postgres-source +description: | + Lists all the sequences in the database ordered by sequence name. + Returns sequence name, schema name, sequence owner, data type of the + sequence, starting value, minimum value, maximum value of the sequence, + the value by which the sequence is incremented, and the last value + generated by generated by the sequence in the current session. ``` The response is a json array with the following elements: @@ -61,6 +61,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-sequences". | +| type | string | true | Must be "postgres-list-sequences". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-stored-procedure.md b/docs/en/resources/tools/postgres/postgres-list-stored-procedure.md index ec03365e5567..cd6a86aa1f7c 100644 --- a/docs/en/resources/tools/postgres/postgres-list-stored-procedure.md +++ b/docs/en/resources/tools/postgres/postgres-list-stored-procedure.md @@ -31,11 +31,11 @@ The tool returns a JSON array where each element represents a stored procedure w ## Example ```yaml -tools: - list_stored_procedure: - kind: postgres-list-stored-procedure - source: postgres-source - description: "Retrieves stored procedure metadata including definitions and owners." +kind: tools +name: list_stored_procedure +type: postgres-list-stored-procedure +source: postgres-source +description: "Retrieves stored procedure metadata including definitions and owners." ``` ### Example Requests diff --git a/docs/en/resources/tools/postgres/postgres-list-table-stats.md b/docs/en/resources/tools/postgres/postgres-list-table-stats.md index 666a126aca3e..cecc8b81d849 100644 --- a/docs/en/resources/tools/postgres/postgres-list-table-stats.md +++ b/docs/en/resources/tools/postgres/postgres-list-table-stats.md @@ -23,11 +23,11 @@ The tool returns a JSON array where each element represents statistics for a tab ## Example ```yaml -tools: - list_table_stats: - kind: postgres-list-table-stats - source: postgres-source - description: "Lists table statistics including size, scans, and bloat metrics." +kind: tools +name: list_table_stats +type: postgres-list-table-stats +source: postgres-source +description: "Lists table statistics including size, scans, and bloat metrics." ``` ### Example Requests diff --git a/docs/en/resources/tools/postgres/postgres-list-tables.md b/docs/en/resources/tools/postgres/postgres-list-tables.md index f40076bd4961..04f56cbfafe3 100644 --- a/docs/en/resources/tools/postgres/postgres-list-tables.md +++ b/docs/en/resources/tools/postgres/postgres-list-tables.md @@ -31,18 +31,18 @@ constraints, indexes, triggers, owner, comment) as JSON for user-created tables ## Example ```yaml -tools: - postgres_list_tables: - kind: postgres-list-tables - source: postgres-source - description: Use this tool to retrieve schema information for all or - specified tables. Output format can be simple (only table names) or detailed. +kind: tools +name: postgres_list_tables +type: postgres-list-tables +source: postgres-source +description: Use this tool to retrieve schema information for all or + specified tables. Output format can be simple (only table names) or detailed. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-tables". | +| type | string | true | Must be "postgres-list-tables". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-tablespaces.md b/docs/en/resources/tools/postgres/postgres-list-tablespaces.md index bf63f61b8f44..5e78bf5cbe62 100644 --- a/docs/en/resources/tools/postgres/postgres-list-tablespaces.md +++ b/docs/en/resources/tools/postgres/postgres-list-tablespaces.md @@ -24,15 +24,15 @@ The `postgres-list-tablespaces` tool lists available tablespaces in the database ## Example ```yaml -tools: - list_tablespaces: - kind: postgres-list-tablespaces - source: postgres-source - description: | - Lists all tablespaces in the database. Returns the tablespace name, - owner name, size in bytes(if the current user has CREATE privileges on - the tablespace, otherwise NULL), internal object ID, the access control - list regarding permissions, and any specific tablespace options. +kind: tools +name: list_tablespaces +type: postgres-list-tablespaces +source: postgres-source +description: | + Lists all tablespaces in the database. Returns the tablespace name, + owner name, size in bytes(if the current user has CREATE privileges on + the tablespace, otherwise NULL), internal object ID, the access control + list regarding permissions, and any specific tablespace options. ``` The response is a json array with the following elements: @@ -51,6 +51,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:-------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-tablespaces". | +| type | string | true | Must be "postgres-list-tablespaces". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-triggers.md b/docs/en/resources/tools/postgres/postgres-list-triggers.md index b2708940013c..5c93e6fc5095 100644 --- a/docs/en/resources/tools/postgres/postgres-list-triggers.md +++ b/docs/en/resources/tools/postgres/postgres-list-triggers.md @@ -31,13 +31,12 @@ tool takes the following input parameters: ## Example ```yaml -```yaml -tools: - list_triggers: - kind: postgres-list-triggers - source: postgres-source - description: | - Lists all non-internal triggers in a database. Returns trigger name, schema name, table name, wether its enabled or disabled, timing (e.g BEFORE/AFTER of the event), the events that cause the trigger to fire such as INSERT, UPDATE, or DELETE, whether the trigger activates per ROW or per STATEMENT, the handler function executed by the trigger and full definition. +kind: tools +name: list_triggers +type: postgres-list-triggers +source: postgres-source +description: | + Lists all non-internal triggers in a database. Returns trigger name, schema name, table name, wether its enabled or disabled, timing (e.g BEFORE/AFTER of the event), the events that cause the trigger to fire such as INSERT, UPDATE, or DELETE, whether the trigger activates per ROW or per STATEMENT, the handler function executed by the trigger and full definition. ``` The response is a json array with the following elements: @@ -60,6 +59,6 @@ The response is a json array with the following elements: | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-triggers". | +| type | string | true | Must be "postgres-list-triggers". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-list-views.md b/docs/en/resources/tools/postgres/postgres-list-views.md index b6f1687f33e5..a99b092276c3 100644 --- a/docs/en/resources/tools/postgres/postgres-list-views.md +++ b/docs/en/resources/tools/postgres/postgres-list-views.md @@ -29,16 +29,16 @@ parameters: ## Example ```yaml -tools: - list_views: - kind: postgres-list-views - source: cloudsql-pg-source +kind: tools +name: list_views +type: postgres-list-views +source: cloudsql-pg-source ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------| -| kind | string | true | Must be "postgres-list-views". | +| type | string | true | Must be "postgres-list-views". | | source | string | true | Name of the source the SQL should execute on. | | description | string | false | Description of the tool that is passed to the agent. | diff --git a/docs/en/resources/tools/postgres/postgres-long-running-transactions.md b/docs/en/resources/tools/postgres/postgres-long-running-transactions.md index 0380ca7c2153..fc264bb6eeb5 100644 --- a/docs/en/resources/tools/postgres/postgres-long-running-transactions.md +++ b/docs/en/resources/tools/postgres/postgres-long-running-transactions.md @@ -60,11 +60,11 @@ LIMIT ## Example ```yaml -tools: - long_running_transactions: - kind: postgres-long-running-transactions - source: postgres-source - description: "Identifies transactions open longer than a threshold and returns details including query text and durations." +kind: tools +name: long_running_transactions +type: postgres-long-running-transactions +source: postgres-source +description: "Identifies transactions open longer than a threshold and returns details including query text and durations." ``` Example response element: diff --git a/docs/en/resources/tools/postgres/postgres-replication-stats.md b/docs/en/resources/tools/postgres/postgres-replication-stats.md index c9dfdc81cba8..b2577539555b 100644 --- a/docs/en/resources/tools/postgres/postgres-replication-stats.md +++ b/docs/en/resources/tools/postgres/postgres-replication-stats.md @@ -23,11 +23,11 @@ This tool takes no parameters. It returns a JSON array; each element represents ## Example ```yaml -tools: - replication_stats: - kind: postgres-replication-stats - source: postgres-source - description: "Lists replication connections and readable WAL lag metrics." +kind: tools +name: replication_stats +type: postgres-replication-stats +source: postgres-source +description: "Lists replication connections and readable WAL lag metrics." ``` Example response element: diff --git a/docs/en/resources/tools/postgres/postgres-sql.md b/docs/en/resources/tools/postgres/postgres-sql.md index 190f9478e3f7..067386b95786 100644 --- a/docs/en/resources/tools/postgres/postgres-sql.md +++ b/docs/en/resources/tools/postgres/postgres-sql.md @@ -34,41 +34,41 @@ of the prepared statement. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT * FROM flights - WHERE airline = $1 - AND flight_number = $2 - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: postgres-sql +source: my-pg-instance +statement: | + SELECT * FROM flights + WHERE airline = $1 + AND flight_number = $2 + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -80,29 +80,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: postgres-sql - source: my-pg-instance - statement: | - SELECT * FROM {{.tableName}} - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: postgres-sql +source: my-pg-instance +statement: | + SELECT * FROM {{.tableName}} +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "postgres-sql". | +| type | string | true | Must be "postgres-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/redis/redis.md b/docs/en/resources/tools/redis/redis.md index 53dc344d6ab1..fade38841695 100644 --- a/docs/en/resources/tools/redis/redis.md +++ b/docs/en/resources/tools/redis/redis.md @@ -42,21 +42,21 @@ to be executed after argument expansion will be `[SADD, userNames, Alice, Sid, B ## Example ```yaml -tools: - user_data_tool: - kind: redis - source: my-redis-instance - description: | - Use this tool to interact with user data stored in Redis. - It can set, retrieve, and delete user-specific information. - commands: - - [SADD, userNames, $userNames] # Array will be flattened into multiple arguments. - - [GET, $userId] - parameters: - - name: userId - type: string - description: The unique identifier for the user. - - name: userNames - type: array - description: The user names to be set. +kind: tools +name: user_data_tool +type: redis +source: my-redis-instance +description: | + Use this tool to interact with user data stored in Redis. + It can set, retrieve, and delete user-specific information. +commands: + - [SADD, userNames, $userNames] # Array will be flattened into multiple arguments. + - [GET, $userId] +parameters: + - name: userId + type: string + description: The unique identifier for the user. + - name: userNames + type: array + description: The user names to be set. ``` diff --git a/docs/en/resources/tools/serverless-spark/serverless-spark-cancel-batch.md b/docs/en/resources/tools/serverless-spark/serverless-spark-cancel-batch.md index 7af6f05ed4bd..61fa321170c6 100644 --- a/docs/en/resources/tools/serverless-spark/serverless-spark-cancel-batch.md +++ b/docs/en/resources/tools/serverless-spark/serverless-spark-cancel-batch.md @@ -30,11 +30,11 @@ The tool inherits the `project` and `location` from the source configuration. ## Example ```yaml -tools: - cancel_spark_batch: - kind: serverless-spark-cancel-batch - source: my-serverless-spark-source - description: Use this tool to cancel a running serverless spark batch operation. +kind: tools +name: cancel_spark_batch +type: serverless-spark-cancel-batch +source: my-serverless-spark-source +description: Use this tool to cancel a running serverless spark batch operation. ``` ## Response Format @@ -47,7 +47,7 @@ tools: | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | -------------------------------------------------- | -| kind | string | true | Must be "serverless-spark-cancel-batch". | +| type | string | true | Must be "serverless-spark-cancel-batch". | | source | string | true | Name of the source the tool should use. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | string[] | false | List of auth services required to invoke this tool | diff --git a/docs/en/resources/tools/serverless-spark/serverless-spark-create-pyspark-batch.md b/docs/en/resources/tools/serverless-spark/serverless-spark-create-pyspark-batch.md index b94d386b2d3f..e0d2a5c097a1 100644 --- a/docs/en/resources/tools/serverless-spark/serverless-spark-create-pyspark-batch.md +++ b/docs/en/resources/tools/serverless-spark/serverless-spark-create-pyspark-batch.md @@ -43,16 +43,16 @@ prebuilt config. ### Example `tools.yaml` ```yaml -tools: - - name: "serverless-spark-create-pyspark-batch" - kind: "serverless-spark-create-pyspark-batch" - source: "my-serverless-spark-source" - runtimeConfig: - properties: - spark.driver.memory: "1024m" - environmentConfig: - executionConfig: - networkUri: "my-network" +kind: tools +name: serverless-spark-create-pyspark-batch +type: serverless-spark-create-pyspark-batch +source: "my-serverless-spark-source" +runtimeConfig: + properties: + spark.driver.memory: "1024m" +environmentConfig: + executionConfig: + networkUri: "my-network" ``` ## Response Format @@ -89,7 +89,7 @@ detailed information. | **field** | **type** | **required** | **description** | | ----------------- | :------: | :----------: | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "serverless-spark-create-pyspark-batch". | +| type | string | true | Must be "serverless-spark-create-pyspark-batch". | | source | string | true | Name of the source the tool should use. | | description | string | false | Description of the tool that is passed to the LLM. | | runtimeConfig | map | false | [Runtime config](https://docs.cloud.google.com/dataproc-serverless/docs/reference/rest/v1/RuntimeConfig) for all batches created with this tool. | diff --git a/docs/en/resources/tools/serverless-spark/serverless-spark-create-spark-batch.md b/docs/en/resources/tools/serverless-spark/serverless-spark-create-spark-batch.md index 8264be00b053..46a0b872927d 100644 --- a/docs/en/resources/tools/serverless-spark/serverless-spark-create-spark-batch.md +++ b/docs/en/resources/tools/serverless-spark/serverless-spark-create-spark-batch.md @@ -48,16 +48,16 @@ prebuilt config. ### Example `tools.yaml` ```yaml -tools: - - name: "serverless-spark-create-spark-batch" - kind: "serverless-spark-create-spark-batch" - source: "my-serverless-spark-source" - runtimeConfig: - properties: - spark.driver.memory: "1024m" - environmentConfig: - executionConfig: - networkUri: "my-network" +kind: tools +name: "serverless-spark-create-spark-batch" +type: "serverless-spark-create-spark-batch" +source: "my-serverless-spark-source" +runtimeConfig: + properties: + spark.driver.memory: "1024m" +environmentConfig: + executionConfig: + networkUri: "my-network" ``` ## Response Format @@ -94,7 +94,7 @@ detailed information. | **field** | **type** | **required** | **description** | | ----------------- | :------: | :----------: | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| kind | string | true | Must be "serverless-spark-create-spark-batch". | +| type | string | true | Must be "serverless-spark-create-spark-batch". | | source | string | true | Name of the source the tool should use. | | description | string | false | Description of the tool that is passed to the LLM. | | runtimeConfig | map | false | [Runtime config](https://docs.cloud.google.com/dataproc-serverless/docs/reference/rest/v1/RuntimeConfig) for all batches created with this tool. | diff --git a/docs/en/resources/tools/serverless-spark/serverless-spark-get-batch.md b/docs/en/resources/tools/serverless-spark/serverless-spark-get-batch.md index 754aab9fd939..a43d6fdb0462 100644 --- a/docs/en/resources/tools/serverless-spark/serverless-spark-get-batch.md +++ b/docs/en/resources/tools/serverless-spark/serverless-spark-get-batch.md @@ -25,11 +25,11 @@ The tool gets the `project` and `location` from the source configuration. ## Example ```yaml -tools: - get_my_batch: - kind: serverless-spark-get-batch - source: my-serverless-spark-source - description: Use this tool to get a serverless spark batch. +kind: tools +name: get_my_batch +type: serverless-spark-get-batch +source: my-serverless-spark-source +description: Use this tool to get a serverless spark batch. ``` ## Response Format @@ -85,7 +85,7 @@ detailed information. | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | -------------------------------------------------- | -| kind | string | true | Must be "serverless-spark-get-batch". | +| type | string | true | Must be "serverless-spark-get-batch". | | source | string | true | Name of the source the tool should use. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | string[] | false | List of auth services required to invoke this tool | diff --git a/docs/en/resources/tools/serverless-spark/serverless-spark-list-batches.md b/docs/en/resources/tools/serverless-spark/serverless-spark-list-batches.md index 9f0e5f0e7ca6..7a7400608468 100644 --- a/docs/en/resources/tools/serverless-spark/serverless-spark-list-batches.md +++ b/docs/en/resources/tools/serverless-spark/serverless-spark-list-batches.md @@ -33,11 +33,11 @@ The tool gets the `project` and `location` from the source configuration. ## Example ```yaml -tools: - list_spark_batches: - kind: serverless-spark-list-batches - source: my-serverless-spark-source - description: Use this tool to list and filter serverless spark batches. +kind: tools +name: list_spark_batches +type: serverless-spark-list-batches +source: my-serverless-spark-source +description: Use this tool to list and filter serverless spark batches. ``` ## Response Format @@ -72,7 +72,7 @@ tools: | **field** | **type** | **required** | **description** | | ------------ | :------: | :----------: | -------------------------------------------------- | -| kind | string | true | Must be "serverless-spark-list-batches". | +| type | string | true | Must be "serverless-spark-list-batches". | | source | string | true | Name of the source the tool should use. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | string[] | false | List of auth services required to invoke this tool | diff --git a/docs/en/resources/tools/singlestore/singlestore-execute-sql.md b/docs/en/resources/tools/singlestore/singlestore-execute-sql.md index c4c007eaf186..fc2e9fbf55ed 100644 --- a/docs/en/resources/tools/singlestore/singlestore-execute-sql.md +++ b/docs/en/resources/tools/singlestore/singlestore-execute-sql.md @@ -25,17 +25,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: singlestore-execute-sql - source: my-s2-instance - description: Use this tool to execute sql statement +kind: tools +name: execute_sql_tool +type: singlestore-execute-sql +source: my-s2-instance +description: Use this tool to execute sql statement ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "singlestore-execute-sql". | +| type | string | true | Must be "singlestore-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/singlestore/singlestore-sql.md b/docs/en/resources/tools/singlestore/singlestore-sql.md index c745e2d9f310..885fbc959f64 100644 --- a/docs/en/resources/tools/singlestore/singlestore-sql.md +++ b/docs/en/resources/tools/singlestore/singlestore-sql.md @@ -27,41 +27,41 @@ form of placeholders `?`. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: singlestore-sql - source: my-s2-instance - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: singlestore-sql +source: my-s2-instance +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -73,29 +73,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: singlestore-sql - source: my-s2-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: singlestore-sql +source: my-s2-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "singlestore-sql". | +| type | string | true | Must be "singlestore-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/snowflake/snowflake-execute-sql.md b/docs/en/resources/tools/snowflake/snowflake-execute-sql.md index 1d6af931bdc1..b5af0fe63f5b 100644 --- a/docs/en/resources/tools/snowflake/snowflake-execute-sql.md +++ b/docs/en/resources/tools/snowflake/snowflake-execute-sql.md @@ -23,18 +23,18 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: snowflake-execute-sql - source: my-snowflake-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: snowflake-execute-sql +source: my-snowflake-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |--------------|:-------------:|:------------:|-----------------------------------------------------------| -| kind | string | true | Must be "snowflake-execute-sql". | +| type | string | true | Must be "snowflake-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | authRequired | array[string] | false | List of auth services that are required to use this tool. | diff --git a/docs/en/resources/tools/snowflake/snowflake-sql.md b/docs/en/resources/tools/snowflake/snowflake-sql.md index d55241e32f8a..b66041cac5f3 100644 --- a/docs/en/resources/tools/snowflake/snowflake-sql.md +++ b/docs/en/resources/tools/snowflake/snowflake-sql.md @@ -26,41 +26,41 @@ first parameter specified, `:2` will be the second parameter, and so on. ## Example ```yaml -tools: - search_flights_by_number: - kind: snowflake-sql - source: my-snowflake-instance - statement: | - SELECT * FROM flights - WHERE airline = :1 - AND flight_number = :2 - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: snowflake-sql +source: my-snowflake-instance +statement: | + SELECT * FROM flights + WHERE airline = :1 + AND flight_number = :2 + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -72,29 +72,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: snowflake - source: my-snowflake-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: snowflake +source: my-snowflake-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "snowflake-sql". | +| type | string | true | Must be "snowflake-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/spanner/spanner-execute-sql.md b/docs/en/resources/tools/spanner/spanner-execute-sql.md index b04e90e34e61..b9e5c6c255d5 100644 --- a/docs/en/resources/tools/spanner/spanner-execute-sql.md +++ b/docs/en/resources/tools/spanner/spanner-execute-sql.md @@ -25,18 +25,18 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: spanner-execute-sql - source: my-spanner-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: spanner-execute-sql +source: my-spanner-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|------------------------------------------------------------------------------------------| -| kind | string | true | Must be "spanner-execute-sql". | +| type | string | true | Must be "spanner-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | readOnly | bool | false | When set to `true`, the `statement` is run as a read-only transaction. Default: `false`. | diff --git a/docs/en/resources/tools/spanner/spanner-list-graphs.md b/docs/en/resources/tools/spanner/spanner-list-graphs.md index e846fdfe77e3..7d8ae63fbcaf 100644 --- a/docs/en/resources/tools/spanner/spanner-list-graphs.md +++ b/docs/en/resources/tools/spanner/spanner-list-graphs.md @@ -35,35 +35,35 @@ source dialect, as Spanner Graph isn't available in the PostgreSQL dialect. ### Basic Usage - List All Graphs ```yaml -sources: - my-spanner-db: - kind: spanner - project: ${SPANNER_PROJECT} - instance: ${SPANNER_INSTANCE} - database: ${SPANNER_DATABASE} - dialect: googlesql # wont work for postgresql - -tools: - list_all_graphs: - kind: spanner-list-graphs - source: my-spanner-db - description: Lists all graphs with their complete schema information +kind: sources +name: my-spanner-db +type: spanner +project: ${SPANNER_PROJECT} +instance: ${SPANNER_INSTANCE} +database: ${SPANNER_DATABASE} +dialect: googlesql # wont work for postgresql +--- +kind: tools +name: list_all_graphs +type: spanner-list-graphs +source: my-spanner-db +description: Lists all graphs with their complete schema information ``` ### List Specific Graphs ```yaml -tools: - list_specific_graphs: - kind: spanner-list-graphs - source: my-spanner-db - description: | - Lists schema information for specific graphs. - Example usage: - { - "graph_names": "FinGraph,SocialGraph", - "output_format": "detailed" - } +kind: tools +name: list_specific_graphs +type: spanner-list-graphs +source: my-spanner-db +description: | + Lists schema information for specific graphs. + Example usage: + { + "graph_names": "FinGraph,SocialGraph", + "output_format": "detailed" + } ``` ## Parameters @@ -235,36 +235,36 @@ comprehensive schema information: ## Example with Agent Integration ```yaml -sources: - spanner-db: - kind: spanner - project: my-project - instance: my-instance - database: my-database - dialect: googlesql - -tools: - schema_inspector: - kind: spanner-list-graphs - source: spanner-db - description: | - Use this tool to inspect database schema information. - You can: - - List all graphs by leaving graph_names empty - - Get specific graph schemas by providing comma-separated graph names - - Choose between simple (names only) or detailed (full schema) output - - Examples: - 1. List all graphs with details: {"output_format": "detailed"} - 2. Get specific graphs: {"graph_names": "FinGraph,SocialGraph", "output_format": "detailed"} - 3. Just get graph names: {"output_format": "simple"} +kind: sources +name: spanner-db +type: spanner +project: my-project +instance: my-instance +database: my-database +dialect: googlesql +--- +kind: tools +name: schema_inspector +type: spanner-list-graphs +source: spanner-db +description: | + Use this tool to inspect database schema information. + You can: + - List all graphs by leaving graph_names empty + - Get specific graph schemas by providing comma-separated graph names + - Choose between simple (names only) or detailed (full schema) output + + Examples: + 1. List all graphs with details: {"output_format": "detailed"} + 2. Get specific graphs: {"graph_names": "FinGraph,SocialGraph", "output_format": "detailed"} + 3. Just get graph names: {"output_format": "simple"} ``` ## Reference | **field** | **type** | **required** | **description** | |--------------|:--------:|:------------:|-----------------------------------------------------------------| -| kind | string | true | Must be "spanner-list-graphs" | +| type | string | true | Must be "spanner-list-graphs" | | source | string | true | Name of the Spanner source to query (dialect must be GoogleSQL) | | description | string | false | Description of the tool that is passed to the LLM | | authRequired | string[] | false | List of auth services required to invoke this tool | diff --git a/docs/en/resources/tools/spanner/spanner-list-tables.md b/docs/en/resources/tools/spanner/spanner-list-tables.md index 3a7f6ea48a2e..d1b196fa9c19 100644 --- a/docs/en/resources/tools/spanner/spanner-list-tables.md +++ b/docs/en/resources/tools/spanner/spanner-list-tables.md @@ -36,35 +36,35 @@ syntax. ### Basic Usage - List All Tables ```yaml -sources: - my-spanner-db: - kind: spanner - project: ${SPANNER_PROJECT} - instance: ${SPANNER_INSTANCE} - database: ${SPANNER_DATABASE} - dialect: googlesql # or postgresql - -tools: - list_all_tables: - kind: spanner-list-tables - source: my-spanner-db - description: Lists all tables with their complete schema information +kind: sources +name: my-spanner-db +type: spanner +project: ${SPANNER_PROJECT} +instance: ${SPANNER_INSTANCE} +database: ${SPANNER_DATABASE} +dialect: googlesql # or postgresql +--- +kind: tools +name: list_all_tables +type: spanner-list-tables +source: my-spanner-db +description: Lists all tables with their complete schema information ``` ### List Specific Tables ```yaml -tools: - list_specific_tables: - kind: spanner-list-tables - source: my-spanner-db - description: | - Lists schema information for specific tables. - Example usage: - { - "table_names": "users,orders,products", - "output_format": "detailed" - } +kind: tools +name: list_specific_tables +type: spanner-list-tables +source: my-spanner-db +description: | + Lists schema information for specific tables. + Example usage: + { + "table_names": "users,orders,products", + "output_format": "detailed" + } ``` ## Parameters @@ -177,36 +177,36 @@ comprehensive schema information: ## Example with Agent Integration ```yaml -sources: - spanner-db: - kind: spanner - project: my-project - instance: my-instance - database: my-database - dialect: googlesql - -tools: - schema_inspector: - kind: spanner-list-tables - source: spanner-db - description: | - Use this tool to inspect database schema information. - You can: - - List all tables by leaving table_names empty - - Get specific table schemas by providing comma-separated table names - - Choose between simple (names only) or detailed (full schema) output - - Examples: - 1. List all tables with details: {"output_format": "detailed"} - 2. Get specific tables: {"table_names": "users,orders", "output_format": "detailed"} - 3. Just get table names: {"output_format": "simple"} +kind: sources +name: spanner-db +type: spanner +project: my-project +instance: my-instance +database: my-database +dialect: googlesql +--- +kind: tools +name: schema_inspector +type: spanner-list-tables +source: spanner-db +description: | + Use this tool to inspect database schema information. + You can: + - List all tables by leaving table_names empty + - Get specific table schemas by providing comma-separated table names + - Choose between simple (names only) or detailed (full schema) output + + Examples: + 1. List all tables with details: {"output_format": "detailed"} + 2. Get specific tables: {"table_names": "users,orders", "output_format": "detailed"} + 3. Just get table names: {"output_format": "simple"} ``` ## Reference | **field** | **type** | **required** | **description** | |--------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "spanner-list-tables" | +| type | string | true | Must be "spanner-list-tables" | | source | string | true | Name of the Spanner source to query | | description | string | false | Description of the tool that is passed to the LLM | | authRequired | string[] | false | List of auth services required to invoke this tool | diff --git a/docs/en/resources/tools/spanner/spanner-sql.md b/docs/en/resources/tools/spanner/spanner-sql.md index edf21254b4c3..221ecc72881b 100644 --- a/docs/en/resources/tools/spanner/spanner-sql.md +++ b/docs/en/resources/tools/spanner/spanner-sql.md @@ -50,80 +50,80 @@ the second parameter, and so on. {{< tabpane persist="header" >}} {{< tab header="GoogleSQL" lang="yaml" >}} -tools: - search_flights_by_number: - kind: spanner-sql - source: my-spanner-instance - statement: | - SELECT * FROM flights - WHERE airline = @airline - AND flight_number = @flight_number - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: spanner-sql +source: my-spanner-instance +statement: | + SELECT * FROM flights + WHERE airline = @airline + AND flight_number = @flight_number + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number {{< /tab >}} {{< tab header="PostgreSQL" lang="yaml" >}} -tools: - search_flights_by_number: - kind: spanner - source: my-spanner-instance - statement: | - SELECT * FROM flights - WHERE airline = $1 - AND flight_number = $2 - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: spanner +source: my-spanner-instance +statement: | + SELECT * FROM flights + WHERE airline = $1 + AND flight_number = $2 + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number {{< /tab >}} {{< /tabpane >}} @@ -137,29 +137,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: spanner - source: my-spanner-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: spanner +source: my-spanner-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "spanner-sql". | +| type | string | true | Must be "spanner-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/sqlite/sqlite-execute-sql.md b/docs/en/resources/tools/sqlite/sqlite-execute-sql.md index 0360154a447e..7e5d29364136 100644 --- a/docs/en/resources/tools/sqlite/sqlite-execute-sql.md +++ b/docs/en/resources/tools/sqlite/sqlite-execute-sql.md @@ -25,17 +25,17 @@ This tool is designed for direct execution of SQL statements. It takes a single ## Example ```yaml -tools: - execute_sql_tool: - kind: sqlite-execute-sql - source: my-sqlite-db - description: Use this tool to execute a SQL statement. +kind: tools +name: execute_sql_tool +type: sqlite-execute-sql +source: my-sqlite-db +description: Use this tool to execute a SQL statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "sqlite-execute-sql". | +| type | string | true | Must be "sqlite-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/sqlite/sqlite-sql.md b/docs/en/resources/tools/sqlite/sqlite-sql.md index ecc714dfb264..de5c9bc48b1c 100644 --- a/docs/en/resources/tools/sqlite/sqlite-sql.md +++ b/docs/en/resources/tools/sqlite/sqlite-sql.md @@ -30,19 +30,19 @@ DDL statements. > names, or other parts of the query. ```yaml -tools: - search-users: - kind: sqlite-sql - source: my-sqlite-db - description: Search users by name and age - parameters: - - name: name - type: string - description: The name to search for - - name: min_age - type: integer - description: Minimum age - statement: SELECT * FROM users WHERE name LIKE ? AND age >= ? +kind: tools +name: search-users +type: sqlite-sql +source: my-sqlite-db +description: Search users by name and age +parameters: + - name: name + type: string + description: The name to search for + - name: min_age + type: integer + description: Minimum age +statement: SELECT * FROM users WHERE name LIKE ? AND age >= ? ``` ### Example with Template Parameters @@ -54,29 +54,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: sqlite-sql - source: my-sqlite-db - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: sqlite-sql +source: my-sqlite-db +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "sqlite-sql". | +| type | string | true | Must be "sqlite-sql". | | source | string | true | Name of the source the SQLite source configuration. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | The SQL statement to execute. | diff --git a/docs/en/resources/tools/tidb/tidb-execute-sql.md b/docs/en/resources/tools/tidb/tidb-execute-sql.md index 8b1e68b8b2b3..fd36d7a845f3 100644 --- a/docs/en/resources/tools/tidb/tidb-execute-sql.md +++ b/docs/en/resources/tools/tidb/tidb-execute-sql.md @@ -25,17 +25,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: tidb-execute-sql - source: my-tidb-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: tidb-execute-sql +source: my-tidb-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------:|:------------:|----------------------------------------------------| -| kind | string | true | Must be "tidb-execute-sql". | +| type | string | true | Must be "tidb-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/tidb/tidb-sql.md b/docs/en/resources/tools/tidb/tidb-sql.md index 3ec6caff458e..8883d7ef4270 100644 --- a/docs/en/resources/tools/tidb/tidb-sql.md +++ b/docs/en/resources/tools/tidb/tidb-sql.md @@ -29,41 +29,41 @@ and expects parameters in the SQL query to be in the form of placeholders `?`. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: tidb-sql - source: my-tidb-instance - statement: | - SELECT * FROM flights - WHERE airline = ? - AND flight_number = ? - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: tidb-sql +source: my-tidb-instance +statement: | + SELECT * FROM flights + WHERE airline = ? + AND flight_number = ? + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -75,29 +75,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: tidb-sql - source: my-tidb-instance - statement: | - SELECT * FROM {{.tableName}}; - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: tidb-sql +source: my-tidb-instance +statement: | + SELECT * FROM {{.tableName}}; +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "tidb-sql". | +| type | string | true | Must be "tidb-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/trino/trino-execute-sql.md b/docs/en/resources/tools/trino/trino-execute-sql.md index 3d18cd6ee82e..3d07133e03ef 100644 --- a/docs/en/resources/tools/trino/trino-execute-sql.md +++ b/docs/en/resources/tools/trino/trino-execute-sql.md @@ -25,17 +25,17 @@ statement against the `source`. ## Example ```yaml -tools: - execute_sql_tool: - kind: trino-execute-sql - source: my-trino-instance - description: Use this tool to execute sql statement. +kind: tools +name: execute_sql_tool +type: trino-execute-sql +source: my-trino-instance +description: Use this tool to execute sql statement. ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "trino-execute-sql". | +| type | string | true | Must be "trino-execute-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | diff --git a/docs/en/resources/tools/trino/trino-sql.md b/docs/en/resources/tools/trino/trino-sql.md index 4b0f8b21d5ac..1ee22b42397a 100644 --- a/docs/en/resources/tools/trino/trino-sql.md +++ b/docs/en/resources/tools/trino/trino-sql.md @@ -28,41 +28,41 @@ The specified SQL statement is executed as a [prepared statement][trino-prepare] > names, or other parts of the query. ```yaml -tools: - search_orders_by_region: - kind: trino-sql - source: my-trino-instance - statement: | - SELECT * FROM hive.sales.orders - WHERE region = ? - AND order_date >= DATE(?) - LIMIT 10 - description: | - Use this tool to get information for orders in a specific region. - Takes a region code and date and returns info on the orders. - Do NOT use this tool with an order id. Do NOT guess a region code or date. - A region code is a code for a geographic region consisting of two-character - region designator and followed by optional subregion. - For example, if given US-WEST, the region is "US-WEST". - Another example for this is EU-CENTRAL, the region is "EU-CENTRAL". - If the tool returns more than one option choose the date closest to today. - Example: - {{ - "region": "US-WEST", - "order_date": "2024-01-01", - }} - Example: - {{ - "region": "EU-CENTRAL", - "order_date": "2024-01-15", - }} - parameters: - - name: region - type: string - description: Region unique identifier - - name: order_date - type: string - description: Order date in YYYY-MM-DD format +kind: tools +name: search_orders_by_region +type: trino-sql +source: my-trino-instance +statement: | + SELECT * FROM hive.sales.orders + WHERE region = ? + AND order_date >= DATE(?) + LIMIT 10 +description: | + Use this tool to get information for orders in a specific region. + Takes a region code and date and returns info on the orders. + Do NOT use this tool with an order id. Do NOT guess a region code or date. + A region code is a code for a geographic region consisting of two-character + region designator and followed by optional subregion. + For example, if given US-WEST, the region is "US-WEST". + Another example for this is EU-CENTRAL, the region is "EU-CENTRAL". + If the tool returns more than one option choose the date closest to today. + Example: + {{ + "region": "US-WEST", + "order_date": "2024-01-01", + }} + Example: + {{ + "region": "EU-CENTRAL", + "order_date": "2024-01-15", + }} +parameters: + - name: region + type: string + description: Region unique identifier + - name: order_date + type: string + description: Order date in YYYY-MM-DD format ``` ### Example with Template Parameters @@ -74,29 +74,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: trino-sql - source: my-trino-instance - statement: | - SELECT * FROM {{.tableName}} - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "hive.sales.orders", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: trino-sql +source: my-trino-instance +statement: | + SELECT * FROM {{.tableName}} +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "hive.sales.orders", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "trino-sql". | +| type | string | true | Must be "trino-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/resources/tools/utility/wait.md b/docs/en/resources/tools/utility/wait.md index 1fde916ce5fa..c58d69a24b36 100644 --- a/docs/en/resources/tools/utility/wait.md +++ b/docs/en/resources/tools/utility/wait.md @@ -24,17 +24,17 @@ and shouldn't be used for production agents. ## Example ```yaml -tools: - wait_for_tool: - kind: wait - description: Use this tool to pause execution for a specified duration. - timeout: 30s +kind: tools +name: wait_for_tool +type: wait +description: Use this tool to pause execution for a specified duration. +timeout: 30s ``` ## Reference | **field** | **type** | **required** | **description** | |-------------|:--------------:|:------------:|-------------------------------------------------------| -| kind | string | true | Must be "wait". | +| type | string | true | Must be "wait". | | description | string | true | Description of the tool that is passed to the LLM. | | timeout | string | true | The default duration the tool can wait for. | diff --git a/docs/en/resources/tools/valkey/valkey.md b/docs/en/resources/tools/valkey/valkey.md index fab9e5e3b130..3b801fcae930 100644 --- a/docs/en/resources/tools/valkey/valkey.md +++ b/docs/en/resources/tools/valkey/valkey.md @@ -38,21 +38,21 @@ to be executed after argument expansion will be `[SADD, userNames, Alice, Sid, B ## Example ```yaml -tools: - user_data_tool: - kind: valkey - source: my-valkey-instance - description: | - Use this tool to interact with user data stored in Valkey. - It can set, retrieve, and delete user-specific information. - commands: - - [SADD, userNames, $userNames] # Array will be flattened into multiple arguments. - - [GET, $userId] - parameters: - - name: userId - type: string - description: The unique identifier for the user. - - name: userNames - type: array - description: The user names to be set. +kind: tools +name: user_data_tool +type: valkey +source: my-valkey-instance +description: | + Use this tool to interact with user data stored in Valkey. + It can set, retrieve, and delete user-specific information. +commands: + - [SADD, userNames, $userNames] # Array will be flattened into multiple arguments. + - [GET, $userId] +parameters: + - name: userId + type: string + description: The unique identifier for the user. + - name: userNames + type: array + description: The user names to be set. ``` diff --git a/docs/en/resources/tools/yuagbytedb/yugabytedb-sql.md b/docs/en/resources/tools/yuagbytedb/yugabytedb-sql.md index e96ab9e6be48..82329c42c8c8 100644 --- a/docs/en/resources/tools/yuagbytedb/yugabytedb-sql.md +++ b/docs/en/resources/tools/yuagbytedb/yugabytedb-sql.md @@ -26,41 +26,41 @@ of the prepared statement. > names, or other parts of the query. ```yaml -tools: - search_flights_by_number: - kind: yugabytedb-sql - source: my-yb-instance - statement: | - SELECT * FROM flights - WHERE airline = $1 - AND flight_number = $2 - LIMIT 10 - description: | - Use this tool to get information for a specific flight. - Takes an airline code and flight number and returns info on the flight. - Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. - A airline code is a code for an airline service consisting of two-character - airline designator and followed by flight number, which is 1 to 4 digit number. - For example, if given CY 0123, the airline is "CY", and flight_number is "123". - Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". - If the tool returns more than one option choose the date closes to today. - Example: - {{ - "airline": "CY", - "flight_number": "888", - }} - Example: - {{ - "airline": "DL", - "flight_number": "1234", - }} - parameters: - - name: airline - type: string - description: Airline unique 2 letter identifier - - name: flight_number - type: string - description: 1 to 4 digit number +kind: tools +name: search_flights_by_number +type: yugabytedb-sql +source: my-yb-instance +statement: | + SELECT * FROM flights + WHERE airline = $1 + AND flight_number = $2 + LIMIT 10 +description: | + Use this tool to get information for a specific flight. + Takes an airline code and flight number and returns info on the flight. + Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. + A airline code is a code for an airline service consisting of two-character + airline designator and followed by flight number, which is 1 to 4 digit number. + For example, if given CY 0123, the airline is "CY", and flight_number is "123". + Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". + If the tool returns more than one option choose the date closes to today. + Example: + {{ + "airline": "CY", + "flight_number": "888", + }} + Example: + {{ + "airline": "DL", + "flight_number": "1234", + }} +parameters: + - name: airline + type: string + description: Airline unique 2 letter identifier + - name: flight_number + type: string + description: 1 to 4 digit number ``` ### Example with Template Parameters @@ -72,29 +72,29 @@ tools: > [templateParameters](..#template-parameters). ```yaml -tools: - list_table: - kind: yugabytedb-sql - source: my-yb-instance - statement: | - SELECT * FROM {{.tableName}} - description: | - Use this tool to list all information from a specific table. - Example: - {{ - "tableName": "flights", - }} - templateParameters: - - name: tableName - type: string - description: Table to select from +kind: tools +name: list_table +type: yugabytedb-sql +source: my-yb-instance +statement: | + SELECT * FROM {{.tableName}} +description: | + Use this tool to list all information from a specific table. + Example: + {{ + "tableName": "flights", + }} +templateParameters: + - name: tableName + type: string + description: Table to select from ``` ## Reference | **field** | **type** | **required** | **description** | |--------------------|:--------------------------------------------:|:------------:|----------------------------------------------------------------------------------------------------------------------------------------| -| kind | string | true | Must be "yugabytedb-sql". | +| type | string | true | Must be "yugabytedb-sql". | | source | string | true | Name of the source the SQL should execute on. | | description | string | true | Description of the tool that is passed to the LLM. | | statement | string | true | SQL statement to execute on. | diff --git a/docs/en/samples/alloydb/ai-nl/alloydb_ai_nl.ipynb b/docs/en/samples/alloydb/ai-nl/alloydb_ai_nl.ipynb index f931a2119b41..d5c0b725a482 100644 --- a/docs/en/samples/alloydb/ai-nl/alloydb_ai_nl.ipynb +++ b/docs/en/samples/alloydb/ai-nl/alloydb_ai_nl.ipynb @@ -801,27 +801,30 @@ "# Create a tools file\n", "tools_file_name = \"tools.yml\"\n", "file_content = f\"\"\"\n", - "sources:\n", - " my-alloydb-pg-source:\n", - " kind: alloydb-postgres\n", - " project: {project_id}\n", - " region: {region}\n", - " cluster: {cluster_name}\n", - " instance: {instance_name}\n", - " database: {database_name}\n", - " user: postgres\n", - " password: {password}\n", - "tools:\n", - " ask_questions:\n", - " kind: alloydb-ai-nl\n", - " source: my-alloydb-pg-source\n", - " description: 'Ask any natural language questions about the tables'\n", - " nlConfig: 'nla_demo_cfg'\n", - " basic_sql:\n", - " kind: postgres-sql\n", - " source: my-alloydb-pg-source\n", - " description: 'Check if db is connected'\n", - " statement: SELECT * from nla_demo.products;\n", + "kind: sources\n", + "name: my-alloydb-pg-source\n", + "type: alloydb-postgres\n", + "project: {project_id}\n", + "region: {region}\n", + "cluster: {cluster_name}\n", + "instance: {instance_name}\n", + "database: {database_name}\n", + "user: postgres\n", + "password: {password}\n", + "---\n", + "kind: tools\n", + "name: ask_questions\n", + "type: alloydb-ai-nl\n", + "source: my-alloydb-pg-source\n", + "description: 'Ask any natural language questions about the tables'\n", + "nlConfig: 'nla_demo_cfg'\n", + "---\n", + "kind: tools\n", + "name: basic_sql\n", + "type: postgres-sql\n", + "source: my-alloydb-pg-source\n", + "description: 'Check if db is connected'\n", + "statement: SELECT * from nla_demo.products;\n", "\"\"\"" ] }, diff --git a/docs/en/samples/alloydb/mcp_quickstart.md b/docs/en/samples/alloydb/mcp_quickstart.md index 82bd5198e788..07034a7f33de 100644 --- a/docs/en/samples/alloydb/mcp_quickstart.md +++ b/docs/en/samples/alloydb/mcp_quickstart.md @@ -143,16 +143,16 @@ First, define the data source for your tools. This tells Toolbox how to connect to your AlloyDB instance. ```yaml -sources: - alloydb-pg-source: - kind: alloydb-postgres - project: YOUR_PROJECT_ID - region: YOUR_REGION - cluster: YOUR_CLUSTER - instance: YOUR_INSTANCE - database: YOUR_DATABASE - user: YOUR_USER - password: YOUR_PASSWORD +kind: sources +name: alloydb-pg-source +type: alloydb-postgres +project: YOUR_PROJECT_ID +region: YOUR_REGION +cluster: YOUR_CLUSTER +instance: YOUR_INSTANCE +database: YOUR_DATABASE +user: YOUR_USER +password: YOUR_PASSWORD ``` Next, define the tools the agent can use. We will categorize them into three @@ -165,76 +165,77 @@ structured queries like managing a shopping cart. Add the following to your `tools.yaml` file: ```yaml -tools: - - access-cart-information: - kind: postgres-sql - source: alloydb-pg-source - description: >- - List items in customer cart. - Use this tool to list items in a customer cart. This tool requires the cart ID. - parameters: - - name: cart_id - type: integer - description: The id of the cart. - statement: | - SELECT - p.name AS product_name, - ci.quantity, - ci.price AS item_price, - (ci.quantity * ci.price) AS total_item_price, - c.created_at AS cart_created_at, - ci.product_id AS product_id - FROM - cart_items ci JOIN cart c ON ci.cart_id = c.cart_id - JOIN products p ON ci.product_id = p.product_id - WHERE - c.cart_id = $1; - - add-to-cart: - kind: postgres-sql - source: alloydb-pg-source - description: >- - Add items to customer cart using the product ID and product prices from the product list. - Use this tool to add items to a customer cart. - This tool requires the cart ID, product ID, quantity, and price. - parameters: - - name: cart_id - type: integer - description: The id of the cart. - - name: product_id - type: integer - description: The id of the product. - - name: quantity - type: integer - description: The quantity of items to add. - - name: price - type: float - description: The price of items to add. - statement: | - INSERT INTO - cart_items (cart_id, product_id, quantity, price) - VALUES($1,$2,$3,$4); - - delete-from-cart: - kind: postgres-sql - source: alloydb-pg-source - description: >- - Remove products from customer cart. - Use this tool to remove products from a customer cart. - This tool requires the cart ID and product ID. - parameters: - - name: cart_id - type: integer - description: The id of the cart. - - name: product_id - type: integer - description: The id of the product. - statement: | - DELETE FROM - cart_items - WHERE - cart_id = $1 AND product_id = $2; +kind: tools +name: access-cart-information +type: postgres-sql +source: alloydb-pg-source +description: >- + List items in customer cart. + Use this tool to list items in a customer cart. This tool requires the cart ID. +parameters: + - name: cart_id + type: integer + description: The id of the cart. +statement: | + SELECT + p.name AS product_name, + ci.quantity, + ci.price AS item_price, + (ci.quantity * ci.price) AS total_item_price, + c.created_at AS cart_created_at, + ci.product_id AS product_id + FROM + cart_items ci JOIN cart c ON ci.cart_id = c.cart_id + JOIN products p ON ci.product_id = p.product_id + WHERE + c.cart_id = $1; +--- +kind: tools +name: add-to-cart +type: postgres-sql +source: alloydb-pg-source +description: >- + Add items to customer cart using the product ID and product prices from the product list. + Use this tool to add items to a customer cart. + This tool requires the cart ID, product ID, quantity, and price. +parameters: + - name: cart_id + type: integer + description: The id of the cart. + - name: product_id + type: integer + description: The id of the product. + - name: quantity + type: integer + description: The quantity of items to add. + - name: price + type: float + description: The price of items to add. +statement: | + INSERT INTO + cart_items (cart_id, product_id, quantity, price) + VALUES($1,$2,$3,$4); +--- +kind: tools +name: delete-from-cart +type: postgres-sql +source: alloydb-pg-source +description: >- + Remove products from customer cart. + Use this tool to remove products from a customer cart. + This tool requires the cart ID and product ID. +parameters: + - name: cart_id + type: integer + description: The id of the cart. + - name: product_id + type: integer + description: The id of the product. +statement: | + DELETE FROM + cart_items + WHERE + cart_id = $1 AND product_id = $2; ``` ### 2. Semantic Search Tools @@ -244,27 +245,28 @@ meaning of a user's query, rather than just keywords. Append the following tools to the `tools` section in your `tools.yaml`: ```yaml - search-product-recommendations: - kind: postgres-sql - source: alloydb-pg-source - description: >- - Search for products based on user needs. - Use this tool to search for products. This tool requires the user's needs. - parameters: - - name: query - type: string - description: The product characteristics - statement: | - SELECT - product_id, - name, - description, - ROUND(CAST(price AS numeric), 2) as price - FROM - products - ORDER BY - embedding('gemini-embedding-001', $1)::vector <=> embedding - LIMIT 5; +kind: tools +name: search-product-recommendations +type: postgres-sql +source: alloydb-pg-source +description: >- + Search for products based on user needs. + Use this tool to search for products. This tool requires the user's needs. +parameters: + - name: query + type: string + description: The product characteristics +statement: | + SELECT + product_id, + name, + description, + ROUND(CAST(price AS numeric), 2) as price + FROM + products + ORDER BY + embedding('gemini-embedding-001', $1)::vector <=> embedding + LIMIT 5; ``` ### 3. Natural Language to SQL (NL2SQL) Tools @@ -286,27 +288,29 @@ to the `tools` section in your `tools.yaml`: section: ```yaml - ask-questions-about-products: - kind: alloydb-ai-nl - source: alloydb-pg-source - nlConfig: flower_shop - description: >- - Ask questions related to products or brands. - Use this tool to ask questions about products or brands. - Always SELECT the IDs of objects when generating queries. +kind: tools +name: ask-questions-about-products +type: alloydb-ai-nl +source: alloydb-pg-source +nlConfig: flower_shop +description: >- + Ask questions related to products or brands. + Use this tool to ask questions about products or brands. + Always SELECT the IDs of objects when generating queries. ``` Finally, group the tools into a `toolset` to make them available to the model. Add the following to the end of your `tools.yaml` file: ```yaml -toolsets: - flower_shop: - - access-cart-information - - search-product-recommendations - - ask-questions-about-products - - add-to-cart - - delete-from-cart +kind: toolsets +name: flower_shop +tools: + - access-cart-information + - search-product-recommendations + - ask-questions-about-products + - add-to-cart + - delete-from-cart ``` For more info on tools, check out the diff --git a/docs/en/samples/bigquery/colab_quickstart_bigquery.ipynb b/docs/en/samples/bigquery/colab_quickstart_bigquery.ipynb index 9c13b6e86ea3..d4da45edb0e9 100644 --- a/docs/en/samples/bigquery/colab_quickstart_bigquery.ipynb +++ b/docs/en/samples/bigquery/colab_quickstart_bigquery.ipynb @@ -273,72 +273,83 @@ "# You can also upload a tools file and use that to run toolbox.\n", "tools_file_name = \"tools.yml\"\n", "file_content = f\"\"\"\n", - "sources:\n", - " my-bigquery-source:\n", - " kind: bigquery\n", - " project: {BIGQUERY_PROJECT}\n", + "kind: sources\n", + "name: my-bigquery-source\n", + "type: bigquery\n", + "project: {BIGQUERY_PROJECT}\n", + "---\n", + "kind: tools\n", + "name: search-hotels-by-name\n", + "type: bigquery-sql\n", + "source: my-bigquery-source\n", + "description: Search for hotels based on name.\n", + "parameters:\n", + " - name: name\n", + " type: string\n", + " description: The name of the hotel.\n", + "statement: SELECT * FROM `{DATASET}.{TABLE_ID}` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%'));\n", + "---\n", + "kind: tools\n", + "name: search-hotels-by-location\n", + "type: bigquery-sql\n", + "source: my-bigquery-source\n", + "description: Search for hotels based on location.\n", + "parameters:\n", + " - name: location\n", + " type: string\n", + " description: The location of the hotel.\n", + "statement: SELECT * FROM `{DATASET}.{TABLE_ID}` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%'));\n", + "---\n", + "kind: tools\n", + "name: book-hotel\n", + "type: bigquery-sql\n", + "source: my-bigquery-source\n", + "description: >-\n", + " Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not.\n", + "parameters:\n", + " - name: hotel_id\n", + " type: integer\n", + " description: The ID of the hotel to book.\n", + "statement: UPDATE `{DATASET}.{TABLE_ID}` SET booked = TRUE WHERE id = @hotel_id;\n", + "---\n", + "kind: tools\n", + "name: update-hotel\n", + "type: bigquery-sql\n", + "source: my-bigquery-source\n", + "description: >-\n", + " Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not.\n", + "parameters:\n", + " - name: checkin_date\n", + " type: string\n", + " description: The new check-in date of the hotel.\n", + " - name: checkout_date\n", + " type: string\n", + " description: The new check-out date of the hotel.\n", + " - name: hotel_id\n", + " type: integer\n", + " description: The ID of the hotel to update.\n", + "statement: >-\n", + " UPDATE `{DATASET}.{TABLE_ID}` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id;\n", + "---\n", + "kind: tools\n", + "name: cancel-hotel\n", + "type: bigquery-sql\n", + "source: my-bigquery-source\n", + "description: Cancel a hotel by its ID.\n", + "parameters:\n", + " - name: hotel_id\n", + " type: integer\n", + " description: The ID of the hotel to cancel.\n", + "statement: UPDATE `{DATASET}.{TABLE_ID}` SET booked = FALSE WHERE id = @hotel_id;\n", + "---\n", + "kind: toolsets\n", + "name: my-toolset\n", "tools:\n", - " search-hotels-by-name:\n", - " kind: bigquery-sql\n", - " source: my-bigquery-source\n", - " description: Search for hotels based on name.\n", - " parameters:\n", - " - name: name\n", - " type: string\n", - " description: The name of the hotel.\n", - " statement: SELECT * FROM `{DATASET}.{TABLE_ID}` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%'));\n", - " search-hotels-by-location:\n", - " kind: bigquery-sql\n", - " source: my-bigquery-source\n", - " description: Search for hotels based on location.\n", - " parameters:\n", - " - name: location\n", - " type: string\n", - " description: The location of the hotel.\n", - " statement: SELECT * FROM `{DATASET}.{TABLE_ID}` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%'));\n", - " book-hotel:\n", - " kind: bigquery-sql\n", - " source: my-bigquery-source\n", - " description: >-\n", - " Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not.\n", - " parameters:\n", - " - name: hotel_id\n", - " type: integer\n", - " description: The ID of the hotel to book.\n", - " statement: UPDATE `{DATASET}.{TABLE_ID}` SET booked = TRUE WHERE id = @hotel_id;\n", - " update-hotel:\n", - " kind: bigquery-sql\n", - " source: my-bigquery-source\n", - " description: >-\n", - " Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not.\n", - " parameters:\n", - " - name: checkin_date\n", - " type: string\n", - " description: The new check-in date of the hotel.\n", - " - name: checkout_date\n", - " type: string\n", - " description: The new check-out date of the hotel.\n", - " - name: hotel_id\n", - " type: integer\n", - " description: The ID of the hotel to update.\n", - " statement: >-\n", - " UPDATE `{DATASET}.{TABLE_ID}` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id;\n", - " cancel-hotel:\n", - " kind: bigquery-sql\n", - " source: my-bigquery-source\n", - " description: Cancel a hotel by its ID.\n", - " parameters:\n", - " - name: hotel_id\n", - " type: integer\n", - " description: The ID of the hotel to cancel.\n", - " statement: UPDATE `{DATASET}.{TABLE_ID}` SET booked = FALSE WHERE id = @hotel_id;\n", - "toolsets:\n", - " my-toolset:\n", - " - search-hotels-by-name\n", - " - search-hotels-by-location\n", - " - book-hotel\n", - " - update-hotel\n", - " - cancel-hotel\n", + " - search-hotels-by-name\n", + " - search-hotels-by-location\n", + " - book-hotel\n", + " - update-hotel\n", + " - cancel-hotel\n", "\"\"\"" ] }, diff --git a/docs/en/samples/bigquery/local_quickstart.md b/docs/en/samples/bigquery/local_quickstart.md index 5735a1a51555..1216270dd12f 100644 --- a/docs/en/samples/bigquery/local_quickstart.md +++ b/docs/en/samples/bigquery/local_quickstart.md @@ -201,66 +201,75 @@ to use BigQuery, and then run the Toolbox server. {{< /notice >}} ```yaml - sources: - my-bigquery-source: - kind: bigquery - project: YOUR_PROJECT_ID - location: us - tools: - search-hotels-by-name: - kind: bigquery-sql - source: my-bigquery-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%')); - search-hotels-by-location: - kind: bigquery-sql - source: my-bigquery-source - description: Search for hotels based on location. - parameters: - - name: location - type: string - description: The location of the hotel. - statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%')); - book-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: >- - Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. - parameters: - - name: hotel_id - type: integer - description: The ID of the hotel to book. - statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = TRUE WHERE id = @hotel_id; - update-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: >- - Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not. - parameters: - - name: checkin_date - type: string - description: The new check-in date of the hotel. - - name: checkout_date - type: string - description: The new check-out date of the hotel. - - name: hotel_id - type: integer - description: The ID of the hotel to update. - statement: >- - UPDATE `YOUR_DATASET_NAME.hotels` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id; - cancel-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: Cancel a hotel by its ID. - parameters: - - name: hotel_id - type: integer - description: The ID of the hotel to cancel. - statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = FALSE WHERE id = @hotel_id; + kind: sources + name: my-bigquery-source + type: bigquery + project: YOUR_PROJECT_ID + location: us + --- + kind: tools + name: search-hotels-by-name + type: bigquery-sql + source: my-bigquery-source + description: Search for hotels based on name. + parameters: + - name: name + type: string + description: The name of the hotel. + statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%')); + --- + kind: tools + name: search-hotels-by-location + type: bigquery-sql + source: my-bigquery-source + description: Search for hotels based on location. + parameters: + - name: location + type: string + description: The location of the hotel. + statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%')); + --- + kind: tools + name: book-hotel + type: bigquery-sql + source: my-bigquery-source + description: >- + Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. + parameters: + - name: hotel_id + type: integer + description: The ID of the hotel to book. + statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = TRUE WHERE id = @hotel_id; + --- + kind: tools + name: update-hotel + type: bigquery-sql + source: my-bigquery-source + description: >- + Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not. + parameters: + - name: checkin_date + type: string + description: The new check-in date of the hotel. + - name: checkout_date + type: string + description: The new check-out date of the hotel. + - name: hotel_id + type: integer + description: The ID of the hotel to update. + statement: >- + UPDATE `YOUR_DATASET_NAME.hotels` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id; + --- + kind: tools + name: cancel-hotel + type: bigquery-sql + source: my-bigquery-source + description: Cancel a hotel by its ID. + parameters: + - name: hotel_id + type: integer + description: The ID of the hotel to cancel. + statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = FALSE WHERE id = @hotel_id; ``` **Important Note on `toolsets`**: The `tools.yaml` content above does not @@ -272,8 +281,9 @@ to use BigQuery, and then run the Toolbox server. ```yaml # Add this to your tools.yaml if using load_toolset("my-toolset") # Ensure it's at the same indentation level as 'sources:' and 'tools:' - toolsets: - my-toolset: + kind: toolsets + name: my-toolset + tools: - search-hotels-by-name - search-hotels-by-location - book-hotel diff --git a/docs/en/samples/bigquery/mcp_quickstart/_index.md b/docs/en/samples/bigquery/mcp_quickstart/_index.md index 53250e06fd8e..1216daac7e27 100644 --- a/docs/en/samples/bigquery/mcp_quickstart/_index.md +++ b/docs/en/samples/bigquery/mcp_quickstart/_index.md @@ -120,73 +120,84 @@ In this section, we will download Toolbox, configure our tools in a {{< /notice >}} ```yaml - sources: - my-bigquery-source: - kind: bigquery - project: YOUR_PROJECT_ID - location: us + kind: sources + name: my-bigquery-source + type: bigquery + project: YOUR_PROJECT_ID + location: us + --- + kind: tools + name: search-hotels-by-name + type: bigquery-sql + source: my-bigquery-source + description: Search for hotels based on name. + parameters: + - name: name + type: string + description: The name of the hotel. + statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%')); + --- + kind: tools + name: search-hotels-by-location + type: bigquery-sql + source: my-bigquery-source + description: Search for hotels based on location. + parameters: + - name: location + type: string + description: The location of the hotel. + statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%')); + --- + kind: tools + name: book-hotel + type: bigquery-sql + source: my-bigquery-source + description: >- + Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. + parameters: + - name: hotel_id + type: integer + description: The ID of the hotel to book. + statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = TRUE WHERE id = @hotel_id; + --- + kind: tools + name: update-hotel + type: bigquery-sql + source: my-bigquery-source + description: >- + Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not. + parameters: + - name: checkin_date + type: string + description: The new check-in date of the hotel. + - name: checkout_date + type: string + description: The new check-out date of the hotel. + - name: hotel_id + type: integer + description: The ID of the hotel to update. + statement: >- + UPDATE `YOUR_DATASET_NAME.hotels` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id; + --- + kind: tools + name: cancel-hotel + type: bigquery-sql + source: my-bigquery-source + description: Cancel a hotel by its ID. + parameters: + - name: hotel_id + type: integer + description: The ID of the hotel to cancel. + statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = FALSE WHERE id = @hotel_id; + --- + kind: toolsets + name: my-toolset tools: - search-hotels-by-name: - kind: bigquery-sql - source: my-bigquery-source - description: Search for hotels based on name. - parameters: - - name: name - type: string - description: The name of the hotel. - statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(name) LIKE LOWER(CONCAT('%', @name, '%')); - search-hotels-by-location: - kind: bigquery-sql - source: my-bigquery-source - description: Search for hotels based on location. - parameters: - - name: location - type: string - description: The location of the hotel. - statement: SELECT * FROM `YOUR_DATASET_NAME.hotels` WHERE LOWER(location) LIKE LOWER(CONCAT('%', @location, '%')); - book-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: >- - Book a hotel by its ID. If the hotel is successfully booked, returns a NULL, raises an error if not. - parameters: - - name: hotel_id - type: integer - description: The ID of the hotel to book. - statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = TRUE WHERE id = @hotel_id; - update-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: >- - Update a hotel's check-in and check-out dates by its ID. Returns a message indicating whether the hotel was successfully updated or not. - parameters: - - name: checkin_date - type: string - description: The new check-in date of the hotel. - - name: checkout_date - type: string - description: The new check-out date of the hotel. - - name: hotel_id - type: integer - description: The ID of the hotel to update. - statement: >- - UPDATE `YOUR_DATASET_NAME.hotels` SET checkin_date = PARSE_DATE('%Y-%m-%d', @checkin_date), checkout_date = PARSE_DATE('%Y-%m-%d', @checkout_date) WHERE id = @hotel_id; - cancel-hotel: - kind: bigquery-sql - source: my-bigquery-source - description: Cancel a hotel by its ID. - parameters: - - name: hotel_id - type: integer - description: The ID of the hotel to cancel. - statement: UPDATE `YOUR_DATASET_NAME.hotels` SET booked = FALSE WHERE id = @hotel_id; - toolsets: - my-toolset: - - search-hotels-by-name - - search-hotels-by-location - - book-hotel - - update-hotel - - cancel-hotel + - search-hotels-by-name + - search-hotels-by-location + - book-hotel + - update-hotel + - cancel-hotel ``` For more info on tools, check out the diff --git a/docs/en/samples/neo4j/mcp_quickstart.md b/docs/en/samples/neo4j/mcp_quickstart.md index fa36ac6ce36b..ebcb70a70e8f 100644 --- a/docs/en/samples/neo4j/mcp_quickstart.md +++ b/docs/en/samples/neo4j/mcp_quickstart.md @@ -61,37 +61,38 @@ Write the following into a `tools.yaml` file: \+ ```yaml -sources: - my-neo4j-source: - kind: neo4j - uri: bolt://localhost:7687 - user: neo4j - password: my-password # Replace with your actual password - -tools: - search-movies-by-actor: - kind: neo4j-cypher - source: my-neo4j-source - description: "Searches for movies an actor has appeared in based on their name. Useful for questions like 'What movies has Tom Hanks been in?'" - parameters: - - name: actor_name - type: string - description: The full name of the actor to search for. - statement: | - MATCH (p:Person {name: $actor_name}) -[:ACTED_IN]-> (m:Movie) - RETURN m.title AS title, m.year AS year, m.genre AS genre - - get-actor-for-movie: - kind: neo4j-cypher - source: my-neo4j-source - description: "Finds the actors who starred in a specific movie. Useful for questions like 'Who acted in Inception?'" - parameters: - - name: movie_title - type: string - description: The exact title of the movie. - statement: | - MATCH (p:Person) -[:ACTED_IN]-> (m:Movie {title: $movie_title}) - RETURN p.name AS actor +kind: sources +name: my-neo4j-source +type: neo4j +uri: bolt://localhost:7687 +user: neo4j +password: my-password # Replace with your actual password +--- +kind: tools +name: search-movies-by-actor +type: neo4j-cypher +source: my-neo4j-source +description: "Searches for movies an actor has appeared in based on their name. Useful for questions like 'What movies has Tom Hanks been in?'" +parameters: + - name: actor_name + type: string + description: The full name of the actor to search for. +statement: | + MATCH (p:Person {name: $actor_name}) -[:ACTED_IN]-> (m:Movie) + RETURN m.title AS title, m.year AS year, m.genre AS genre +--- +kind: tools +name: get-actor-for-movie +type: neo4j-cypher +source: my-neo4j-source +description: "Finds the actors who starred in a specific movie. Useful for questions like 'Who acted in Inception?'" +parameters: + - name: movie_title + type: string + description: The exact title of the movie. +statement: | + MATCH (p:Person) -[:ACTED_IN]-> (m:Movie {title: $movie_title}) + RETURN p.name AS actor ``` . **Start the Toolbox server.** diff --git a/docs/en/samples/snowflake/_index.md b/docs/en/samples/snowflake/_index.md index 0149544ebaf7..6f3ca05e8dc9 100644 --- a/docs/en/samples/snowflake/_index.md +++ b/docs/en/samples/snowflake/_index.md @@ -79,32 +79,33 @@ You have two options: Create a `tools.yaml` file and add the following content. You must replace the placeholders with your actual Snowflake configuration. ```yaml -sources: - snowflake-source: - kind: snowflake - account: ${SNOWFLAKE_ACCOUNT} - user: ${SNOWFLAKE_USER} - password: ${SNOWFLAKE_PASSWORD} - database: ${SNOWFLAKE_DATABASE} - schema: ${SNOWFLAKE_SCHEMA} - warehouse: ${SNOWFLAKE_WAREHOUSE} - role: ${SNOWFLAKE_ROLE} - -tools: - execute_sql: - kind: snowflake-execute-sql - source: snowflake-source - description: Use this tool to execute SQL. - - list_tables: - kind: snowflake-sql - source: snowflake-source - description: "Lists detailed schema information for user-created tables." - statement: | - SELECT table_name, table_type - FROM information_schema.tables - WHERE table_schema = current_schema() - ORDER BY table_name; +kind: sources +name: snowflake-source +type: snowflake +account: ${SNOWFLAKE_ACCOUNT} +user: ${SNOWFLAKE_USER} +password: ${SNOWFLAKE_PASSWORD} +database: ${SNOWFLAKE_DATABASE} +schema: ${SNOWFLAKE_SCHEMA} +warehouse: ${SNOWFLAKE_WAREHOUSE} +role: ${SNOWFLAKE_ROLE} +--- +kind: tools +name: execute_sql +type: snowflake-execute-sql +source: snowflake-source +description: Use this tool to execute SQL. +--- +kind: tools +name: list_tables +type: snowflake-sql +source: snowflake-source +description: "Lists detailed schema information for user-created tables." +statement: | + SELECT table_name, table_type + FROM information_schema.tables + WHERE table_schema = current_schema() + ORDER BY table_name; ``` For more info on tools, check out the diff --git a/docs/en/samples/snowflake/snowflake-config.yaml b/docs/en/samples/snowflake/snowflake-config.yaml index 085433e34659..29660de2bf24 100644 --- a/docs/en/samples/snowflake/snowflake-config.yaml +++ b/docs/en/samples/snowflake/snowflake-config.yaml @@ -12,57 +12,60 @@ # See the License for the specific language governing permissions and # limitations under the License. -sources: - my-snowflake-db: - kind: snowflake - account: ${SNOWFLAKE_ACCOUNT} - user: ${SNOWFLAKE_USER} - password: ${SNOWFLAKE_PASSWORD} - database: ${SNOWFLAKE_DATABASE} - schema: ${SNOWFLAKE_SCHEMA} - warehouse: ${SNOWFLAKE_WAREHOUSE} # Optional, defaults to COMPUTE_WH if not set - role: ${SNOWFLAKE_ROLE} # Optional, defaults to ACCOUNTADMIN if not set - +kind: sources +name: my-snowflake-db +type: snowflake +account: ${SNOWFLAKE_ACCOUNT} +user: ${SNOWFLAKE_USER} +password: ${SNOWFLAKE_PASSWORD} +database: ${SNOWFLAKE_DATABASE} +schema: ${SNOWFLAKE_SCHEMA} +warehouse: ${SNOWFLAKE_WAREHOUSE} # Optional, defaults to COMPUTE_WH if not set +role: ${SNOWFLAKE_ROLE} # Optional, defaults to ACCOUNTADMIN if not set +--- +kind: tools +name: execute_sql +type: snowflake-execute-sql +source: my-snowflake-db +description: Execute arbitrary SQL statements on Snowflake +--- +kind: tools +name: get_customer_orders +type: snowflake-sql +source: my-snowflake-db +description: Get orders for a specific customer +statement: | + SELECT o.order_id, o.order_date, o.total_amount, o.status + FROM orders o + WHERE o.customer_id = $1 + ORDER BY o.order_date DESC +parameters: + - name: customer_id + type: string + description: The customer ID to look up orders for +--- +kind: tools +name: daily_sales_report +type: snowflake-sql +source: my-snowflake-db +description: Generate daily sales report for a specific date +statement: | + SELECT + DATE(order_date) as sales_date, + COUNT(*) as total_orders, + SUM(total_amount) as total_revenue, + AVG(total_amount) as avg_order_value + FROM orders + WHERE DATE(order_date) = $1 + GROUP BY DATE(order_date) +parameters: + - name: report_date + type: string + description: The date to generate report for (YYYY-MM-DD format) +--- +kind: toolsets +name: snowflake-analytics tools: - execute_sql: - kind: snowflake-execute-sql - source: my-snowflake-db - description: Execute arbitrary SQL statements on Snowflake - - get_customer_orders: - kind: snowflake-sql - source: my-snowflake-db - description: Get orders for a specific customer - statement: | - SELECT o.order_id, o.order_date, o.total_amount, o.status - FROM orders o - WHERE o.customer_id = $1 - ORDER BY o.order_date DESC - parameters: - - name: customer_id - type: string - description: The customer ID to look up orders for - - daily_sales_report: - kind: snowflake-sql - source: my-snowflake-db - description: Generate daily sales report for a specific date - statement: | - SELECT - DATE(order_date) as sales_date, - COUNT(*) as total_orders, - SUM(total_amount) as total_revenue, - AVG(total_amount) as avg_order_value - FROM orders - WHERE DATE(order_date) = $1 - GROUP BY DATE(order_date) - parameters: - - name: report_date - type: string - description: The date to generate report for (YYYY-MM-DD format) - -toolsets: - snowflake-analytics: - - execute_sql - - get_customer_orders - - daily_sales_report + - execute_sql + - get_customer_orders + - daily_sales_report diff --git a/internal/auth/auth.go b/internal/auth/auth.go index e8f15e4f11eb..5fd30d1f4572 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -21,13 +21,13 @@ import ( // AuthServiceConfig is the interface for configuring authentication services. type AuthServiceConfig interface { - AuthServiceConfigKind() string + AuthServiceConfigType() string Initialize() (AuthService, error) } // AuthService is the interface for authentication services. type AuthService interface { - AuthServiceKind() string + AuthServiceType() string GetName() string GetClaimsFromHeader(context.Context, http.Header) (map[string]any, error) ToConfig() AuthServiceConfig diff --git a/internal/auth/google/google.go b/internal/auth/google/google.go index 90cb80958915..40279505575e 100644 --- a/internal/auth/google/google.go +++ b/internal/auth/google/google.go @@ -23,7 +23,7 @@ import ( "google.golang.org/api/idtoken" ) -const AuthServiceKind string = "google" +const AuthServiceType string = "google" // validate interface var _ auth.AuthServiceConfig = Config{} @@ -31,13 +31,13 @@ var _ auth.AuthServiceConfig = Config{} // Auth service configuration type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` ClientID string `yaml:"clientId" validate:"required"` } -// Returns the auth service kind -func (cfg Config) AuthServiceConfigKind() string { - return AuthServiceKind +// Returns the auth service type +func (cfg Config) AuthServiceConfigType() string { + return AuthServiceType } // Initialize a Google auth service @@ -55,9 +55,9 @@ type AuthService struct { Config } -// Returns the auth service kind -func (a AuthService) AuthServiceKind() string { - return AuthServiceKind +// Returns the auth service type +func (a AuthService) AuthServiceType() string { + return AuthServiceType } func (a AuthService) ToConfig() auth.AuthServiceConfig { diff --git a/internal/embeddingmodels/embeddingmodels.go b/internal/embeddingmodels/embeddingmodels.go index d038dd231ed3..5f82ee32f1fb 100644 --- a/internal/embeddingmodels/embeddingmodels.go +++ b/internal/embeddingmodels/embeddingmodels.go @@ -22,12 +22,12 @@ import ( // EmbeddingModelConfig is the interface for configuring embedding models. type EmbeddingModelConfig interface { - EmbeddingModelConfigKind() string + EmbeddingModelConfigType() string Initialize(context.Context) (EmbeddingModel, error) } type EmbeddingModel interface { - EmbeddingModelKind() string + EmbeddingModelType() string ToConfig() EmbeddingModelConfig EmbedParameters(context.Context, []string) ([][]float32, error) } diff --git a/internal/embeddingmodels/gemini/gemini.go b/internal/embeddingmodels/gemini/gemini.go index 1a31060e7b86..fa63b12acb73 100644 --- a/internal/embeddingmodels/gemini/gemini.go +++ b/internal/embeddingmodels/gemini/gemini.go @@ -23,22 +23,22 @@ import ( "google.golang.org/genai" ) -const EmbeddingModelKind string = "gemini" +const EmbeddingModelType string = "gemini" // validate interface var _ embeddingmodels.EmbeddingModelConfig = Config{} type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Model string `yaml:"model" validate:"required"` ApiKey string `yaml:"apiKey"` Dimension int32 `yaml:"dimension"` } -// Returns the embedding model kind -func (cfg Config) EmbeddingModelConfigKind() string { - return EmbeddingModelKind +// Returns the embedding model type +func (cfg Config) EmbeddingModelConfigType() string { + return EmbeddingModelType } // Initialize a Gemini embedding model @@ -69,9 +69,9 @@ type EmbeddingModel struct { Config } -// Returns the embedding model kind -func (m EmbeddingModel) EmbeddingModelKind() string { - return EmbeddingModelKind +// Returns the embedding model type +func (m EmbeddingModel) EmbeddingModelType() string { + return EmbeddingModelType } func (m EmbeddingModel) ToConfig() embeddingmodels.EmbeddingModelConfig { diff --git a/internal/embeddingmodels/gemini/gemini_test.go b/internal/embeddingmodels/gemini/gemini_test.go index c4c3b8dcdcad..e04e1df1b6ba 100644 --- a/internal/embeddingmodels/gemini/gemini_test.go +++ b/internal/embeddingmodels/gemini/gemini_test.go @@ -15,9 +15,9 @@ package gemini_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/embeddingmodels" "github.com/googleapis/genai-toolbox/internal/embeddingmodels/gemini" @@ -34,15 +34,15 @@ func TestParseFromYamlGemini(t *testing.T) { { desc: "basic example", in: ` - embeddingModels: - my-gemini-model: - kind: gemini - model: text-embedding-004 + kind: embeddingModels + name: my-gemini-model + type: gemini + model: text-embedding-004 `, want: map[string]embeddingmodels.EmbeddingModelConfig{ "my-gemini-model": gemini.Config{ Name: "my-gemini-model", - Kind: gemini.EmbeddingModelKind, + Type: gemini.EmbeddingModelType, Model: "text-embedding-004", }, }, @@ -50,17 +50,17 @@ func TestParseFromYamlGemini(t *testing.T) { { desc: "full example with optional fields", in: ` - embeddingModels: - complex-gemini: - kind: gemini - model: text-embedding-004 - apiKey: "test-api-key" - dimension: 768 + kind: embeddingModels + name: complex-gemini + type: gemini + model: text-embedding-004 + apiKey: "test-api-key" + dimension: 768 `, want: map[string]embeddingmodels.EmbeddingModelConfig{ "complex-gemini": gemini.Config{ Name: "complex-gemini", - Kind: gemini.EmbeddingModelKind, + Type: gemini.EmbeddingModelType, Model: "text-embedding-004", ApiKey: "test-api-key", Dimension: 768, @@ -70,16 +70,13 @@ func TestParseFromYamlGemini(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Models server.EmbeddingModelConfigs `yaml:"embeddingModels"` - }{} // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, got, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Models) { - t.Fatalf("incorrect parse: %v", cmp.Diff(tc.want, got.Models)) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: %v", cmp.Diff(tc.want, got)) } }) } @@ -93,32 +90,29 @@ func TestFailParseFromYamlGemini(t *testing.T) { { desc: "missing required model field", in: ` - embeddingModels: - bad-model: - kind: gemini + kind: embeddingModels + name: bad-model + type: gemini `, // Removed the specific model name from the prefix to match your output - err: "unable to parse as \"gemini\": Key: 'Config.Model' Error:Field validation for 'Model' failed on the 'required' tag", + err: "error unmarshaling embeddingModels: unable to parse as \"bad-model\": Key: 'Config.Model' Error:Field validation for 'Model' failed on the 'required' tag", }, { desc: "unknown field", in: ` - embeddingModels: - bad-field: - kind: gemini - model: text-embedding-004 - invalid_param: true + kind: embeddingModels + name: bad-field + type: gemini + model: text-embedding-004 + invalid_param: true `, // Updated to match the specific line-starting format of your error output - err: "unable to parse as \"gemini\": [1:1] unknown field \"invalid_param\"\n> 1 | invalid_param: true\n ^\n 2 | kind: gemini\n 3 | model: text-embedding-004", + err: "error unmarshaling embeddingModels: unable to parse as \"bad-field\": [1:1] unknown field \"invalid_param\"\n> 1 | invalid_param: true\n ^\n 2 | model: text-embedding-004\n 3 | name: bad-field\n 4 | type: gemini", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Models server.EmbeddingModelConfigs `yaml:"embeddingModels"` - }{} - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/prompts/custom/custom.go b/internal/prompts/custom/custom.go index 312b53613c2f..4ed44c465191 100644 --- a/internal/prompts/custom/custom.go +++ b/internal/prompts/custom/custom.go @@ -25,12 +25,12 @@ import ( type Message = prompts.Message -const kind = "custom" +const resourceType = "custom" -// init registers this prompt kind with the prompt framework. +// init registers this prompt type with the prompt framework. func init() { - if !prompts.Register(kind, newConfig) { - panic(fmt.Sprintf("prompt kind %q already registered", kind)) + if !prompts.Register(resourceType, newConfig) { + panic(fmt.Sprintf("prompt type %q already registered", resourceType)) } } @@ -56,8 +56,8 @@ type Config struct { var _ prompts.PromptConfig = Config{} var _ prompts.Prompt = Prompt{} -func (c Config) PromptConfigKind() string { - return kind +func (c Config) PromptConfigType() string { + return resourceType } func (c Config) Initialize() (prompts.Prompt, error) { diff --git a/internal/prompts/custom/custom_test.go b/internal/prompts/custom/custom_test.go index ff411c7b8b9e..4f9ad565e5ed 100644 --- a/internal/prompts/custom/custom_test.go +++ b/internal/prompts/custom/custom_test.go @@ -42,7 +42,7 @@ func TestConfig(t *testing.T) { Arguments: testArgs, } - // initialize and check kind + // initialize and check type p, err := cfg.Initialize() if err != nil { t.Fatalf("Initialize() failed: %v", err) @@ -50,8 +50,8 @@ func TestConfig(t *testing.T) { if p == nil { t.Fatal("Initialize() returned a nil prompt") } - if cfg.PromptConfigKind() != "custom" { - t.Errorf("PromptConfigKind() = %q, want %q", cfg.PromptConfigKind(), "custom") + if cfg.PromptConfigType() != "custom" { + t.Errorf("PromptConfigType() = %q, want %q", cfg.PromptConfigType(), "custom") } t.Run("Manifest", func(t *testing.T) { diff --git a/internal/prompts/prompts.go b/internal/prompts/prompts.go index bac784c4c511..ae8312c49e69 100644 --- a/internal/prompts/prompts.go +++ b/internal/prompts/prompts.go @@ -30,40 +30,40 @@ var promptRegistry = make(map[string]PromptConfigFactory) // Register allows individual prompt packages to register their configuration // factory function. This is typically called from an init() function in the -// prompt's package. It associates a 'kind' string with a function that can +// prompt's package. It associates a 'type' string with a function that can // produce the specific PromptConfig type. It returns true if the registration was -// successful, and false if a prompt with the same kind was already registered. -func Register(kind string, factory PromptConfigFactory) bool { - if _, exists := promptRegistry[kind]; exists { - // Prompt with this kind already exists, do not overwrite. +// successful, and false if a prompt with the same type was already registered. +func Register(resourceType string, factory PromptConfigFactory) bool { + if _, exists := promptRegistry[resourceType]; exists { + // Prompt with this type already exists, do not overwrite. return false } - promptRegistry[kind] = factory + promptRegistry[resourceType] = factory return true } -// DecodeConfig looks up the registered factory for the given kind and uses it +// DecodeConfig looks up the registered factory for the given type and uses it // to decode the prompt configuration. -func DecodeConfig(ctx context.Context, kind, name string, decoder *yaml.Decoder) (PromptConfig, error) { - factory, found := promptRegistry[kind] - if !found && kind == "" { - kind = "custom" - factory, found = promptRegistry[kind] +func DecodeConfig(ctx context.Context, resourceType, name string, decoder *yaml.Decoder) (PromptConfig, error) { + factory, found := promptRegistry[resourceType] + if !found && resourceType == "" { + resourceType = "custom" + factory, found = promptRegistry[resourceType] } if !found { - return nil, fmt.Errorf("unknown prompt kind: %q", kind) + return nil, fmt.Errorf("unknown prompt type: %q", resourceType) } promptConfig, err := factory(ctx, name, decoder) if err != nil { - return nil, fmt.Errorf("unable to parse prompt %q as kind %q: %w", name, kind, err) + return nil, fmt.Errorf("unable to parse prompt %q as resourceType %q: %w", name, resourceType, err) } return promptConfig, nil } type PromptConfig interface { - PromptConfigKind() string + PromptConfigType() string Initialize() (Prompt, error) } diff --git a/internal/prompts/prompts_test.go b/internal/prompts/prompts_test.go index d0fe0a95f58f..72fbe5c3ce94 100644 --- a/internal/prompts/prompts_test.go +++ b/internal/prompts/prompts_test.go @@ -29,16 +29,16 @@ import ( type mockPromptConfig struct { name string - kind string + Type string } -func (m *mockPromptConfig) PromptConfigKind() string { return m.kind } +func (m *mockPromptConfig) PromptConfigType() string { return m.Type } func (m *mockPromptConfig) Initialize() (prompts.Prompt, error) { return nil, nil } var errMockFactory = errors.New("mock factory error") func mockFactory(ctx context.Context, name string, decoder *yaml.Decoder) (prompts.PromptConfig, error) { - return &mockPromptConfig{name: name, kind: "mockKind"}, nil + return &mockPromptConfig{name: name, Type: "mockType"}, nil } func mockErrorFactory(ctx context.Context, name string, decoder *yaml.Decoder) (prompts.PromptConfig, error) { @@ -50,17 +50,17 @@ func TestRegistry(t *testing.T) { ctx := context.Background() t.Run("RegisterAndDecodeSuccess", func(t *testing.T) { - kind := "testKindSuccess" - if !prompts.Register(kind, mockFactory) { + resourceType := "testTypeSuccess" + if !prompts.Register(resourceType, mockFactory) { t.Fatal("expected registration to succeed") } // This should fail because we are registering a duplicate - if prompts.Register(kind, mockFactory) { + if prompts.Register(resourceType, mockFactory) { t.Fatal("expected duplicate registration to fail") } decoder := yaml.NewDecoder(strings.NewReader("")) - config, err := prompts.DecodeConfig(ctx, kind, "testPrompt", decoder) + config, err := prompts.DecodeConfig(ctx, resourceType, "testPrompt", decoder) if err != nil { t.Fatalf("expected DecodeConfig to succeed, but got error: %v", err) } @@ -69,25 +69,25 @@ func TestRegistry(t *testing.T) { } }) - t.Run("DecodeUnknownKind", func(t *testing.T) { + t.Run("DecodeUnknownType", func(t *testing.T) { decoder := yaml.NewDecoder(strings.NewReader("")) - _, err := prompts.DecodeConfig(ctx, "unregisteredKind", "testPrompt", decoder) + _, err := prompts.DecodeConfig(ctx, "unregisteredType", "testPrompt", decoder) if err == nil { - t.Fatal("expected an error for unknown kind, but got nil") + t.Fatal("expected an error for unknown type, but got nil") } - if !strings.Contains(err.Error(), "unknown prompt kind") { - t.Errorf("expected error to contain 'unknown prompt kind', but got: %v", err) + if !strings.Contains(err.Error(), "unknown prompt type") { + t.Errorf("expected error to contain 'unknown prompt type', but got: %v", err) } }) t.Run("FactoryReturnsError", func(t *testing.T) { - kind := "testKindError" - if !prompts.Register(kind, mockErrorFactory) { + resourceType := "testTypeError" + if !prompts.Register(resourceType, mockErrorFactory) { t.Fatal("expected registration to succeed") } decoder := yaml.NewDecoder(strings.NewReader("")) - _, err := prompts.DecodeConfig(ctx, kind, "testPrompt", decoder) + _, err := prompts.DecodeConfig(ctx, resourceType, "testPrompt", decoder) if err == nil { t.Fatal("expected an error from the factory, but got nil") } @@ -100,13 +100,13 @@ func TestRegistry(t *testing.T) { decoder := yaml.NewDecoder(strings.NewReader("description: A test prompt")) config, err := prompts.DecodeConfig(ctx, "", "testDefaultPrompt", decoder) if err != nil { - t.Fatalf("expected DecodeConfig with empty kind to succeed, but got error: %v", err) + t.Fatalf("expected DecodeConfig with empty type to succeed, but got error: %v", err) } if config == nil { - t.Fatal("expected a non-nil config for default kind") + t.Fatal("expected a non-nil config for default type") } - if config.PromptConfigKind() != "custom" { - t.Errorf("expected default kind to be 'custom', but got %q", config.PromptConfigKind()) + if config.PromptConfigType() != "custom" { + t.Errorf("expected default type to be 'custom', but got %q", config.PromptConfigType()) } }) } diff --git a/internal/server/common_test.go b/internal/server/common_test.go index 39aca55be39d..54109ac467f9 100644 --- a/internal/server/common_test.go +++ b/internal/server/common_test.go @@ -87,6 +87,10 @@ func (t MockTool) RequiresClientAuthorization(tools.SourceProvider) (bool, error return t.requiresClientAuthrorization, nil } +func (t MockTool) GetParameters() parameters.Parameters { + return t.Params +} + func (t MockTool) McpManifest() tools.McpManifest { properties := make(map[string]parameters.ParameterMcpManifest) required := make([]string, 0) diff --git a/internal/server/config.go b/internal/server/config.go index 652e7547de7b..48f623b0eab5 100644 --- a/internal/server/config.go +++ b/internal/server/config.go @@ -14,8 +14,10 @@ package server import ( + "bytes" "context" "fmt" + "io" "regexp" "strings" @@ -127,315 +129,264 @@ func (s *StringLevel) Type() string { return "stringLevel" } -// SourceConfigs is a type used to allow unmarshal of the data source config map type SourceConfigs map[string]sources.SourceConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &SourceConfigs{} - -func (c *SourceConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(SourceConfigs) - // Parse the 'kind' fields for each source - var raw map[string]util.DelayedUnmarshaler - if err := unmarshal(&raw); err != nil { - return err - } - - for name, u := range raw { - // Unmarshal to a general type that ensure it capture all fields - var v map[string]any - if err := u.Unmarshal(&v); err != nil { - return fmt.Errorf("unable to unmarshal %q: %w", name, err) - } - - kind, ok := v["kind"] - if !ok { - return fmt.Errorf("missing 'kind' field for source %q", name) - } - kindStr, ok := kind.(string) - if !ok { - return fmt.Errorf("invalid 'kind' field for source %q (must be a string)", name) - } - - yamlDecoder, err := util.NewStrictDecoder(v) - if err != nil { - return fmt.Errorf("error creating YAML decoder for source %q: %w", name, err) - } - - sourceConfig, err := sources.DecodeConfig(ctx, kindStr, name, yamlDecoder) - if err != nil { - return err - } - (*c)[name] = sourceConfig - } - return nil -} - -// AuthServiceConfigs is a type used to allow unmarshal of the data authService config map type AuthServiceConfigs map[string]auth.AuthServiceConfig +type EmbeddingModelConfigs map[string]embeddingmodels.EmbeddingModelConfig +type ToolConfigs map[string]tools.ToolConfig +type ToolsetConfigs map[string]tools.ToolsetConfig +type PromptConfigs map[string]prompts.PromptConfig +type PromptsetConfigs map[string]prompts.PromptsetConfig -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &AuthServiceConfigs{} - -func (c *AuthServiceConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(AuthServiceConfigs) - // Parse the 'kind' fields for each authService - var raw map[string]util.DelayedUnmarshaler - if err := unmarshal(&raw); err != nil { - return err - } - - for name, u := range raw { - var v map[string]any - if err := u.Unmarshal(&v); err != nil { - return fmt.Errorf("unable to unmarshal %q: %w", name, err) +func UnmarshalResourceConfig(ctx context.Context, raw []byte) (SourceConfigs, AuthServiceConfigs, EmbeddingModelConfigs, ToolConfigs, ToolsetConfigs, PromptConfigs, error) { + // prepare configs map + var sourceConfigs SourceConfigs + var authServiceConfigs AuthServiceConfigs + var embeddingModelConfigs EmbeddingModelConfigs + var toolConfigs ToolConfigs + var toolsetConfigs ToolsetConfigs + var promptConfigs PromptConfigs + // promptset configs is not yet supported + + decoder := yaml.NewDecoder(bytes.NewReader(raw)) + // for loop to unmarshal documents with the `---` separator + for { + var resource map[string]any + if err := decoder.DecodeContext(ctx, &resource); err != nil { + if err == io.EOF { + break + } + return nil, nil, nil, nil, nil, nil, fmt.Errorf("unable to decode YAML document: %w", err) } - - kind, ok := v["kind"] - if !ok { - return fmt.Errorf("missing 'kind' field for %q", name) + var kind, name string + var ok bool + if kind, ok = resource["kind"].(string); !ok { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("missing 'kind' field or it is not a string: %v", resource) } - - dec, err := util.NewStrictDecoder(v) - if err != nil { - return fmt.Errorf("error creating decoder: %w", err) + if name, ok = resource["name"].(string); !ok { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("missing 'name' field or it is not a string") } + // remove 'kind' from map for strict unmarshaling + delete(resource, "kind") + switch kind { - case google.AuthServiceKind: - actual := google.Config{Name: name} - if err := dec.DecodeContext(ctx, &actual); err != nil { - return fmt.Errorf("unable to parse as %q: %w", kind, err) + case "sources": + c, err := UnmarshalYAMLSourceConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) + } + if sourceConfigs == nil { + sourceConfigs = make(SourceConfigs) + } + sourceConfigs[name] = c + case "authServices": + c, err := UnmarshalYAMLAuthServiceConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) } - (*c)[name] = actual + if authServiceConfigs == nil { + authServiceConfigs = make(AuthServiceConfigs) + } + authServiceConfigs[name] = c + case "tools": + c, err := UnmarshalYAMLToolConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) + } + if toolConfigs == nil { + toolConfigs = make(ToolConfigs) + } + toolConfigs[name] = c + case "toolsets": + c, err := UnmarshalYAMLToolsetConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) + } + if toolsetConfigs == nil { + toolsetConfigs = make(ToolsetConfigs) + } + toolsetConfigs[name] = c + case "embeddingModels": + c, err := UnmarshalYAMLEmbeddingModelConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) + } + if embeddingModelConfigs == nil { + embeddingModelConfigs = make(EmbeddingModelConfigs) + } + embeddingModelConfigs[name] = c + case "prompts": + c, err := UnmarshalYAMLPromptConfig(ctx, name, resource) + if err != nil { + return nil, nil, nil, nil, nil, nil, fmt.Errorf("error unmarshaling %s: %s", kind, err) + } + if promptConfigs == nil { + promptConfigs = make(PromptConfigs) + } + promptConfigs[name] = c default: - return fmt.Errorf("%q is not a valid kind of auth source", kind) + return nil, nil, nil, nil, nil, nil, fmt.Errorf("invalid kind %s", kind) } } - return nil + return sourceConfigs, authServiceConfigs, embeddingModelConfigs, toolConfigs, toolsetConfigs, promptConfigs, nil } -// EmbeddingModelConfigs is a type used to allow unmarshal of the embedding model config map -type EmbeddingModelConfigs map[string]embeddingmodels.EmbeddingModelConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &EmbeddingModelConfigs{} - -func (c *EmbeddingModelConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(EmbeddingModelConfigs) - // Parse the 'kind' fields for each embedding model - var raw map[string]util.DelayedUnmarshaler - if err := unmarshal(&raw); err != nil { - return err +func UnmarshalYAMLSourceConfig(ctx context.Context, name string, r map[string]any) (sources.SourceConfig, error) { + resourceType, ok := r["type"].(string) + if !ok { + return nil, fmt.Errorf("missing 'type' field or it is not a string") } - - for name, u := range raw { - // Unmarshal to a general type that ensure it capture all fields - var v map[string]any - if err := u.Unmarshal(&v); err != nil { - return fmt.Errorf("unable to unmarshal embedding model %q: %w", name, err) - } - - kind, ok := v["kind"] - if !ok { - return fmt.Errorf("missing 'kind' field for embedding model %q", name) - } - - dec, err := util.NewStrictDecoder(v) - if err != nil { - return fmt.Errorf("error creating decoder: %w", err) - } - switch kind { - case gemini.EmbeddingModelKind: - actual := gemini.Config{Name: name} - if err := dec.DecodeContext(ctx, &actual); err != nil { - return fmt.Errorf("unable to parse as %q: %w", kind, err) - } - (*c)[name] = actual - default: - return fmt.Errorf("%q is not a valid kind of auth source", kind) - } + dec, err := util.NewStrictDecoder(r) + if err != nil { + return nil, fmt.Errorf("error creating decoder: %w", err) } - return nil + sourceConfig, err := sources.DecodeConfig(ctx, resourceType, name, dec) + if err != nil { + return nil, err + } + return sourceConfig, nil } -// ToolConfigs is a type used to allow unmarshal of the tool configs -type ToolConfigs map[string]tools.ToolConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &ToolConfigs{} - -func (c *ToolConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(ToolConfigs) - // Parse the 'kind' fields for each source - var raw map[string]util.DelayedUnmarshaler - if err := unmarshal(&raw); err != nil { - return err +func UnmarshalYAMLAuthServiceConfig(ctx context.Context, name string, r map[string]any) (auth.AuthServiceConfig, error) { + resourceType, ok := r["type"].(string) + if !ok { + return nil, fmt.Errorf("missing 'type' field or it is not a string") } + if resourceType != google.AuthServiceType { + return nil, fmt.Errorf("%s is not a valid type of auth service", resourceType) + } + dec, err := util.NewStrictDecoder(r) + if err != nil { + return nil, fmt.Errorf("error creating decoder: %s", err) + } + actual := google.Config{Name: name} + if err := dec.DecodeContext(ctx, &actual); err != nil { + return nil, fmt.Errorf("unable to parse as %s: %w", name, err) + } + return actual, nil +} - for name, u := range raw { - err := NameValidation(name) - if err != nil { - return err - } - var v map[string]any - if err := u.Unmarshal(&v); err != nil { - return fmt.Errorf("unable to unmarshal %q: %w", name, err) - } - - // `authRequired` and `useClientOAuth` cannot be specified together - if v["authRequired"] != nil && v["useClientOAuth"] == true { - return fmt.Errorf("`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method") - } - - // Make `authRequired` an empty list instead of nil for Tool manifest - if v["authRequired"] == nil { - v["authRequired"] = []string{} - } +func UnmarshalYAMLEmbeddingModelConfig(ctx context.Context, name string, r map[string]any) (embeddingmodels.EmbeddingModelConfig, error) { + resourceType, ok := r["type"].(string) + if !ok { + return nil, fmt.Errorf("missing 'type' field or it is not a string") + } + if resourceType != gemini.EmbeddingModelType { + return nil, fmt.Errorf("%s is not a valid type of embedding model", resourceType) + } + dec, err := util.NewStrictDecoder(r) + if err != nil { + return nil, fmt.Errorf("error creating decoder: %s", err) + } + actual := gemini.Config{Name: name} + if err := dec.DecodeContext(ctx, &actual); err != nil { + return nil, fmt.Errorf("unable to parse as %q: %w", name, err) + } + return actual, nil +} - kindVal, ok := v["kind"] - if !ok { - return fmt.Errorf("missing 'kind' field for tool %q", name) - } - kindStr, ok := kindVal.(string) - if !ok { - return fmt.Errorf("invalid 'kind' field for tool %q (must be a string)", name) - } +func UnmarshalYAMLToolConfig(ctx context.Context, name string, r map[string]any) (tools.ToolConfig, error) { + resourceType, ok := r["type"].(string) + if !ok { + return nil, fmt.Errorf("missing 'type' field or it is not a string") + } + // `authRequired` and `useClientOAuth` cannot be specified together + if r["authRequired"] != nil && r["useClientOAuth"] == true { + return nil, fmt.Errorf("`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method") + } + // Make `authRequired` an empty list instead of nil for Tool manifest + if r["authRequired"] == nil { + r["authRequired"] = []string{} + } - // validify parameter references - if rawParams, ok := v["parameters"]; ok { - if paramsList, ok := rawParams.([]any); ok { - // Turn params into a map - validParamNames := make(map[string]bool) - for _, rawP := range paramsList { - if pMap, ok := rawP.(map[string]any); ok { - if pName, ok := pMap["name"].(string); ok && pName != "" { - validParamNames[pName] = true - } + // validify parameter references + if rawParams, ok := r["parameters"]; ok { + if paramsList, ok := rawParams.([]any); ok { + // Turn params into a map + validParamNames := make(map[string]bool) + for _, rawP := range paramsList { + if pMap, ok := rawP.(map[string]any); ok { + if pName, ok := pMap["name"].(string); ok && pName != "" { + validParamNames[pName] = true } } + } - // Validate references - for i, rawP := range paramsList { - pMap, ok := rawP.(map[string]any) - if !ok { - continue - } + // Validate references + for i, rawP := range paramsList { + pMap, ok := rawP.(map[string]any) + if !ok { + continue + } - pName, _ := pMap["name"].(string) - refName, _ := pMap["valueFromParam"].(string) + pName, _ := pMap["name"].(string) + refName, _ := pMap["valueFromParam"].(string) - if refName != "" { - // Check if the referenced parameter exists - if !validParamNames[refName] { - return fmt.Errorf("tool %q config error: parameter %q (index %d) references '%q' in the 'valueFromParam' field, which is not a defined parameter", name, pName, i, refName) - } + if refName != "" { + // Check if the referenced parameter exists + if !validParamNames[refName] { + return nil, fmt.Errorf("tool %q config error: parameter %q (index %d) references '%q' in the 'valueFromParam' field, which is not a defined parameter", name, pName, i, refName) + } - // Check for self-reference - if refName == pName { - return fmt.Errorf("tool %q config error: parameter %q cannot copy value from itself", name, pName) - } + // Check for self-reference + if refName == pName { + return nil, fmt.Errorf("tool %q config error: parameter %q cannot copy value from itself", name, pName) } } } } - yamlDecoder, err := util.NewStrictDecoder(v) - if err != nil { - return fmt.Errorf("error creating YAML decoder for tool %q: %w", name, err) - } - - toolCfg, err := tools.DecodeConfig(ctx, kindStr, name, yamlDecoder) - if err != nil { - return err - } - (*c)[name] = toolCfg } - return nil -} - -// ToolsetConfigs is a type used to allow unmarshal of the toolset configs -type ToolsetConfigs map[string]tools.ToolsetConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &ToolsetConfigs{} -func (c *ToolsetConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(ToolsetConfigs) - - var raw map[string][]string - if err := unmarshal(&raw); err != nil { - return err + dec, err := util.NewStrictDecoder(r) + if err != nil { + return nil, fmt.Errorf("error creating decoder: %s", err) } - - for name, toolList := range raw { - (*c)[name] = tools.ToolsetConfig{Name: name, ToolNames: toolList} + toolCfg, err := tools.DecodeConfig(ctx, resourceType, name, dec) + if err != nil { + return nil, err } - return nil + return toolCfg, nil } -// PromptConfigs is a type used to allow unmarshal of the prompt configs -type PromptConfigs map[string]prompts.PromptConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &PromptConfigs{} - -func (c *PromptConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(PromptConfigs) - var raw map[string]util.DelayedUnmarshaler - if err := unmarshal(&raw); err != nil { - return err +func UnmarshalYAMLToolsetConfig(ctx context.Context, name string, r map[string]any) (tools.ToolsetConfig, error) { + var toolsetConfig tools.ToolsetConfig + toolList, ok := r["tools"].([]any) + if !ok { + return toolsetConfig, fmt.Errorf("tools is missing or not a list of strings: %v", r) } - - for name, u := range raw { - var v map[string]any - if err := u.Unmarshal(&v); err != nil { - return fmt.Errorf("unable to unmarshal prompt %q: %w", name, err) - } - - // Look for the 'kind' field. If it's not present, kindStr will be an - // empty string, which prompts.DecodeConfig will correctly default to "custom". - var kindStr string - if kindVal, ok := v["kind"]; ok { - var isString bool - kindStr, isString = kindVal.(string) - if !isString { - return fmt.Errorf("invalid 'kind' field for prompt %q (must be a string)", name) - } - } - - // Create a new, strict decoder for this specific prompt's data. - yamlDecoder, err := util.NewStrictDecoder(v) - if err != nil { - return fmt.Errorf("error creating YAML decoder for prompt %q: %w", name, err) - } - - // Use the central registry to decode the prompt based on its kind. - promptCfg, err := prompts.DecodeConfig(ctx, kindStr, name, yamlDecoder) - if err != nil { - return err - } - (*c)[name] = promptCfg + justTools := map[string]any{"tools": toolList} + dec, err := util.NewStrictDecoder(justTools) + if err != nil { + return toolsetConfig, fmt.Errorf("error creating decoder: %s", err) } - return nil + var raw map[string][]string + if err := dec.DecodeContext(ctx, &raw); err != nil { + return toolsetConfig, fmt.Errorf("unable to unmarshal tools: %s", err) + } + return tools.ToolsetConfig{Name: name, ToolNames: raw["tools"]}, nil } -// PromptsetConfigs is a type used to allow unmarshal of the PromptsetConfigs configs -type PromptsetConfigs map[string]prompts.PromptsetConfig - -// validate interface -var _ yaml.InterfaceUnmarshalerContext = &PromptsetConfigs{} - -func (c *PromptsetConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interface{}) error) error { - *c = make(PromptsetConfigs) - - var raw map[string][]string - if err := unmarshal(&raw); err != nil { - return err +func UnmarshalYAMLPromptConfig(ctx context.Context, name string, r map[string]any) (prompts.PromptConfig, error) { + // Look for the 'type' field. If it's not present, typeStr will be an + // empty string, which prompts.DecodeConfig will correctly default to "custom". + var resourceType string + if typeVal, ok := r["type"]; ok { + var isString bool + resourceType, isString = typeVal.(string) + if !isString { + return nil, fmt.Errorf("invalid 'type' field for prompt %q (must be a string)", name) + } + } + dec, err := util.NewStrictDecoder(r) + if err != nil { + return nil, fmt.Errorf("error creating decoder: %s", err) } - for name, promptList := range raw { - (*c)[name] = prompts.PromptsetConfig{Name: name, PromptNames: promptList} + // Use the central registry to decode the prompt based on its type. + promptCfg, err := prompts.DecodeConfig(ctx, resourceType, name, dec) + if err != nil { + return nil, err } - return nil + return promptCfg, nil } // Tools naming validation is added in the MCP v2025-11-25, but we'll be diff --git a/internal/server/resources/resources_test.go b/internal/server/resources/resources_test.go index ad4bfdd32656..e0682a27a958 100644 --- a/internal/server/resources/resources_test.go +++ b/internal/server/resources/resources_test.go @@ -32,7 +32,7 @@ func TestUpdateServer(t *testing.T) { "example-source": &alloydbpg.Source{ Config: alloydbpg.Config{ Name: "example-alloydb-source", - Kind: "alloydb-postgres", + Type: "alloydb-postgres", }, }, } @@ -92,7 +92,7 @@ func TestUpdateServer(t *testing.T) { "example-source2": &alloydbpg.Source{ Config: alloydbpg.Config{ Name: "example-alloydb-source2", - Kind: "alloydb-postgres", + Type: "alloydb-postgres", }, }, } diff --git a/internal/server/server.go b/internal/server/server.go index 961ffc48a3a6..f77c50411362 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -86,7 +86,7 @@ func InitializeConfigs(ctx context.Context, cfg ServerConfig) ( childCtx, span := instrumentation.Tracer.Start( ctx, "toolbox/server/source/init", - trace.WithAttributes(attribute.String("source_kind", sc.SourceConfigKind())), + trace.WithAttributes(attribute.String("source_type", sc.SourceConfigType())), trace.WithAttributes(attribute.String("source_name", name)), ) defer span.End() @@ -114,7 +114,7 @@ func InitializeConfigs(ctx context.Context, cfg ServerConfig) ( _, span := instrumentation.Tracer.Start( ctx, "toolbox/server/auth/init", - trace.WithAttributes(attribute.String("auth_kind", sc.AuthServiceConfigKind())), + trace.WithAttributes(attribute.String("auth_type", sc.AuthServiceConfigType())), trace.WithAttributes(attribute.String("auth_name", name)), ) defer span.End() @@ -142,7 +142,7 @@ func InitializeConfigs(ctx context.Context, cfg ServerConfig) ( _, span := instrumentation.Tracer.Start( ctx, "toolbox/server/embeddingmodel/init", - trace.WithAttributes(attribute.String("model_kind", ec.EmbeddingModelConfigKind())), + trace.WithAttributes(attribute.String("model_type", ec.EmbeddingModelConfigType())), trace.WithAttributes(attribute.String("model_name", name)), ) defer span.End() @@ -170,7 +170,7 @@ func InitializeConfigs(ctx context.Context, cfg ServerConfig) ( _, span := instrumentation.Tracer.Start( ctx, "toolbox/server/tool/init", - trace.WithAttributes(attribute.String("tool_kind", tc.ToolConfigKind())), + trace.WithAttributes(attribute.String("tool_type", tc.ToolConfigType())), trace.WithAttributes(attribute.String("tool_name", name)), ) defer span.End() @@ -239,7 +239,7 @@ func InitializeConfigs(ctx context.Context, cfg ServerConfig) ( _, span := instrumentation.Tracer.Start( ctx, "toolbox/server/prompt/init", - trace.WithAttributes(attribute.String("prompt_kind", pc.PromptConfigKind())), + trace.WithAttributes(attribute.String("prompt_type", pc.PromptConfigType())), trace.WithAttributes(attribute.String("prompt_name", name)), ) defer span.End() diff --git a/internal/server/server_test.go b/internal/server/server_test.go index c13df83be414..ab809fc579d6 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -141,7 +141,7 @@ func TestUpdateServer(t *testing.T) { "example-source": &alloydbpg.Source{ Config: alloydbpg.Config{ Name: "example-alloydb-source", - Kind: "alloydb-postgres", + Type: "alloydb-postgres", }, }, } diff --git a/internal/sources/alloydbadmin/alloydbadmin.go b/internal/sources/alloydbadmin/alloydbadmin.go index 633c7eb73e55..6a9938d93684 100644 --- a/internal/sources/alloydbadmin/alloydbadmin.go +++ b/internal/sources/alloydbadmin/alloydbadmin.go @@ -32,14 +32,14 @@ import ( "google.golang.org/api/option" ) -const SourceKind string = "alloydb-admin" +const SourceType string = "alloydb-admin" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -53,13 +53,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` DefaultProject string `yaml:"defaultProject"` UseClientOAuth bool `yaml:"useClientOAuth"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -106,8 +106,8 @@ type Source struct { Service *alloydbrestapi.Service } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/alloydbadmin/alloydbadmin_test.go b/internal/sources/alloydbadmin/alloydbadmin_test.go index b8af21c386ae..ae4fd9b5e14e 100644 --- a/internal/sources/alloydbadmin/alloydbadmin_test.go +++ b/internal/sources/alloydbadmin/alloydbadmin_test.go @@ -15,9 +15,9 @@ package alloydbadmin_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,14 +34,14 @@ func TestParseFromYamlAlloyDBAdmin(t *testing.T) { { desc: "basic example", in: ` - sources: - my-alloydb-admin-instance: - kind: alloydb-admin + kind: sources + name: my-alloydb-admin-instance + type: alloydb-admin `, want: map[string]sources.SourceConfig{ "my-alloydb-admin-instance": alloydbadmin.Config{ Name: "my-alloydb-admin-instance", - Kind: alloydbadmin.SourceKind, + Type: alloydbadmin.SourceType, UseClientOAuth: false, }, }, @@ -49,15 +49,15 @@ func TestParseFromYamlAlloyDBAdmin(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-alloydb-admin-instance: - kind: alloydb-admin - useClientOAuth: true + kind: sources + name: my-alloydb-admin-instance + type: alloydb-admin + useClientOAuth: true `, want: map[string]sources.SourceConfig{ "my-alloydb-admin-instance": alloydbadmin.Config{ Name: "my-alloydb-admin-instance", - Kind: alloydbadmin.SourceKind, + Type: alloydbadmin.SourceType, UseClientOAuth: true, }, }, @@ -65,16 +65,13 @@ func TestParseFromYamlAlloyDBAdmin(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -89,30 +86,27 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-alloydb-admin-instance: - kind: alloydb-admin - project: test-project + kind: sources + name: my-alloydb-admin-instance + type: alloydb-admin + project: test-project `, - err: "unable to parse source \"my-alloydb-admin-instance\" as \"alloydb-admin\": [2:1] unknown field \"project\"\n 1 | kind: alloydb-admin\n> 2 | project: test-project\n ^\n", + err: "error unmarshaling sources: unable to parse source \"my-alloydb-admin-instance\" as \"alloydb-admin\": [2:1] unknown field \"project\"\n 1 | name: my-alloydb-admin-instance\n> 2 | project: test-project\n ^\n 3 | type: alloydb-admin", }, { desc: "missing required field", in: ` - sources: - my-alloydb-admin-instance: - useClientOAuth: true + kind: sources + name: my-alloydb-admin-instance + useClientOAuth: true `, - err: "missing 'kind' field for source \"my-alloydb-admin-instance\"", + err: "error unmarshaling sources: missing 'type' field or it is not a string", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/alloydbpg/alloydb_pg.go b/internal/sources/alloydbpg/alloydb_pg.go index 58d8600ebdba..74c4eb3a26fa 100644 --- a/internal/sources/alloydbpg/alloydb_pg.go +++ b/internal/sources/alloydbpg/alloydb_pg.go @@ -29,14 +29,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "alloydb-postgres" +const SourceType string = "alloydb-postgres" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,7 +50,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Region string `yaml:"region" validate:"required"` Cluster string `yaml:"cluster" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -90,8 +90,8 @@ type Source struct { Pool *pgxpool.Pool } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -183,7 +183,7 @@ func getConnectionConfig(ctx context.Context, user, pass, dbname string) (string func initAlloyDBPgConnectionPool(ctx context.Context, tracer trace.Tracer, name, project, region, cluster, instance, ipType, user, pass, dbname string) (*pgxpool.Pool, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() dsn, useIAM, err := getConnectionConfig(ctx, user, pass, dbname) diff --git a/internal/sources/alloydbpg/alloydb_pg_test.go b/internal/sources/alloydbpg/alloydb_pg_test.go index f0ddc57ef903..b1b374b6a4b4 100644 --- a/internal/sources/alloydbpg/alloydb_pg_test.go +++ b/internal/sources/alloydbpg/alloydb_pg_test.go @@ -15,9 +15,9 @@ package alloydbpg_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,21 +34,21 @@ func TestParseFromYamlAlloyDBPg(t *testing.T) { { desc: "basic example", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - project: my-project - region: my-region - cluster: my-cluster - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: alloydb-postgres + project: my-project + region: my-region + cluster: my-cluster + instance: my-instance + database: my_db + user: my_user + password: my_pass `, want: map[string]sources.SourceConfig{ "my-pg-instance": alloydbpg.Config{ Name: "my-pg-instance", - Kind: alloydbpg.SourceKind, + Type: alloydbpg.SourceType, Project: "my-project", Region: "my-region", Cluster: "my-cluster", @@ -63,22 +63,22 @@ func TestParseFromYamlAlloyDBPg(t *testing.T) { { desc: "public ipType", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - project: my-project - region: my-region - cluster: my-cluster - instance: my-instance - ipType: Public - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: alloydb-postgres + project: my-project + region: my-region + cluster: my-cluster + instance: my-instance + ipType: Public + database: my_db + user: my_user + password: my_pass `, want: map[string]sources.SourceConfig{ "my-pg-instance": alloydbpg.Config{ Name: "my-pg-instance", - Kind: alloydbpg.SourceKind, + Type: alloydbpg.SourceType, Project: "my-project", Region: "my-region", Cluster: "my-cluster", @@ -93,22 +93,22 @@ func TestParseFromYamlAlloyDBPg(t *testing.T) { { desc: "private ipType", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - project: my-project - region: my-region - cluster: my-cluster - instance: my-instance - ipType: private - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: alloydb-postgres + project: my-project + region: my-region + cluster: my-cluster + instance: my-instance + ipType: private + database: my_db + user: my_user + password: my_pass `, want: map[string]sources.SourceConfig{ "my-pg-instance": alloydbpg.Config{ Name: "my-pg-instance", - Kind: alloydbpg.SourceKind, + Type: alloydbpg.SourceType, Project: "my-project", Region: "my-region", Cluster: "my-cluster", @@ -123,16 +123,13 @@ func TestParseFromYamlAlloyDBPg(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -147,60 +144,56 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid ipType", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - project: my-project - region: my-region - cluster: my-cluster - instance: my-instance - ipType: fail - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: alloydb-postgres + project: my-project + region: my-region + cluster: my-cluster + instance: my-instance + ipType: fail + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", }, { desc: "extra field", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - project: my-project - region: my-region - cluster: my-cluster - instance: my-instance - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-pg-instance + type: alloydb-postgres + project: my-project + region: my-region + cluster: my-cluster + instance: my-instance + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": [3:1] unknown field \"foo\"\n 1 | cluster: my-cluster\n 2 | database: my_db\n> 3 | foo: bar\n ^\n 4 | instance: my-instance\n 5 | kind: alloydb-postgres\n 6 | password: my_pass\n 7 | ", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": [3:1] unknown field \"foo\"\n 1 | cluster: my-cluster\n 2 | database: my_db\n> 3 | foo: bar\n ^\n 4 | instance: my-instance\n 5 | name: my-pg-instance\n 6 | password: my_pass\n 7 | ", }, { desc: "missing required field", in: ` - sources: - my-pg-instance: - kind: alloydb-postgres - region: my-region - cluster: my-cluster - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: alloydb-postgres + region: my-region + cluster: my-cluster + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"alloydb-postgres\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/bigquery/bigquery.go b/internal/sources/bigquery/bigquery.go index b24378c858e2..527c4e0c3b10 100644 --- a/internal/sources/bigquery/bigquery.go +++ b/internal/sources/bigquery/bigquery.go @@ -41,7 +41,7 @@ import ( "google.golang.org/api/option" ) -const SourceKind string = "bigquery" +const SourceType string = "bigquery" // CloudPlatformScope is a broad scope for Google Cloud Platform services. const CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform" @@ -65,8 +65,8 @@ type BigQuerySessionProvider func(ctx context.Context) (*Session, error) type DataplexClientCreator func(tokenString string) (*dataplexapi.CatalogClient, error) func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -81,7 +81,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // BigQuery configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Location string `yaml:"location"` WriteMode string `yaml:"writeMode"` @@ -119,9 +119,9 @@ func (s *StringOrStringSlice) UnmarshalYAML(unmarshal func(any) error) error { return fmt.Errorf("cannot unmarshal %T into StringOrStringSlice", v) } -func (r Config) SourceConfigKind() string { - // Returns BigQuery source kind - return SourceKind +func (r Config) SourceConfigType() string { + // Returns BigQuery source type + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { if r.WriteMode == "" { @@ -302,9 +302,9 @@ type Session struct { LastUsed time.Time } -func (s *Source) SourceKind() string { - // Returns BigQuery Google SQL source kind - return SourceKind +func (s *Source) SourceType() string { + // Returns BigQuery Google SQL source type + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -665,7 +665,7 @@ func initBigQueryConnection( impersonateServiceAccount string, scopes []string, ) (*bigqueryapi.Client, *bigqueryrestapi.Service, oauth2.TokenSource, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) @@ -741,7 +741,7 @@ func initBigQueryConnectionWithOAuthToken( tokenString string, wantRestService bool, ) (*bigqueryapi.Client, *bigqueryrestapi.Service, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Construct token source token := &oauth2.Token{ @@ -801,7 +801,7 @@ func initDataplexConnection( var clientCreator DataplexClientCreator var err error - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) diff --git a/internal/sources/bigquery/bigquery_test.go b/internal/sources/bigquery/bigquery_test.go index a23f1b47bd67..d2883a94f7d2 100644 --- a/internal/sources/bigquery/bigquery_test.go +++ b/internal/sources/bigquery/bigquery_test.go @@ -15,18 +15,18 @@ package bigquery_test import ( + "context" "math/big" "reflect" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" - "go.opentelemetry.io/otel/trace/noop" - "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/bigquery" "github.com/googleapis/genai-toolbox/internal/testutils" "github.com/googleapis/genai-toolbox/internal/util" + "go.opentelemetry.io/otel/trace/noop" ) func TestParseFromYamlBigQuery(t *testing.T) { @@ -38,15 +38,15 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "basic example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project + kind: sources + name: my-instance + type: bigquery + project: my-project `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "", WriteMode: "", @@ -56,17 +56,17 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "all fields specified", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: asia - writeMode: blocked + kind: sources + name: my-instance + type: bigquery + project: my-project + location: asia + writeMode: blocked `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "asia", WriteMode: "blocked", @@ -77,17 +77,17 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - useClientOAuth: true + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + useClientOAuth: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "us", UseClientOAuth: true, @@ -97,18 +97,18 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "with allowed datasets example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - allowedDatasets: - - my_dataset + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + allowedDatasets: + - my_dataset `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "us", AllowedDatasets: []string{"my_dataset"}, @@ -118,17 +118,17 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "with service account impersonation example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - impersonateServiceAccount: service-account@my-project.iam.gserviceaccount.com + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + impersonateServiceAccount: service-account@my-project.iam.gserviceaccount.com `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "us", ImpersonateServiceAccount: "service-account@my-project.iam.gserviceaccount.com", @@ -138,19 +138,19 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "with custom scopes example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - scopes: - - https://www.googleapis.com/auth/bigquery - - https://www.googleapis.com/auth/cloud-platform + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + scopes: + - https://www.googleapis.com/auth/bigquery + - https://www.googleapis.com/auth/cloud-platform `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "us", Scopes: []string{"https://www.googleapis.com/auth/bigquery", "https://www.googleapis.com/auth/cloud-platform"}, @@ -160,17 +160,17 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "with max query result rows example", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - maxQueryResultRows: 10 + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + maxQueryResultRows: 10 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": bigquery.Config{ Name: "my-instance", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "my-project", Location: "us", MaxQueryResultRows: 10, @@ -180,20 +180,15 @@ func TestParseFromYamlBigQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Fatalf("incorrect parse (-want +got):\n%s", diff) } }) } - } func TestFailParseFromYaml(t *testing.T) { @@ -205,33 +200,29 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-instance: - kind: bigquery - project: my-project - location: us - foo: bar + kind: sources + name: my-instance + type: bigquery + project: my-project + location: us + foo: bar `, - err: "unable to parse source \"my-instance\" as \"bigquery\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | kind: bigquery\n 3 | location: us\n 4 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"bigquery\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | location: us\n 3 | name: my-instance\n 4 | project: my-project\n 5 | ", }, { desc: "missing required field", in: ` - sources: - my-instance: - kind: bigquery - location: us + kind: sources + name: my-instance + type: bigquery + location: us `, - err: "unable to parse source \"my-instance\" as \"bigquery\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"bigquery\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } @@ -260,7 +251,7 @@ func TestInitialize_MaxQueryResultRows(t *testing.T) { desc: "default value", cfg: bigquery.Config{ Name: "test-default", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "test-project", UseClientOAuth: true, }, @@ -270,7 +261,7 @@ func TestInitialize_MaxQueryResultRows(t *testing.T) { desc: "configured value", cfg: bigquery.Config{ Name: "test-configured", - Kind: bigquery.SourceKind, + Type: bigquery.SourceType, Project: "test-project", UseClientOAuth: true, MaxQueryResultRows: 100, diff --git a/internal/sources/bigtable/bigtable.go b/internal/sources/bigtable/bigtable.go index 22daf64c3755..16b5f3065156 100644 --- a/internal/sources/bigtable/bigtable.go +++ b/internal/sources/bigtable/bigtable.go @@ -27,14 +27,14 @@ import ( "google.golang.org/api/option" ) -const SourceKind string = "bigtable" +const SourceType string = "bigtable" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -48,13 +48,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Instance string `yaml:"instance" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -77,8 +77,8 @@ type Source struct { Client *bigtable.Client } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -179,7 +179,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, configParam param func initBigtableClient(ctx context.Context, tracer trace.Tracer, name, project, instance string) (*bigtable.Client, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Set up Bigtable data operations client. diff --git a/internal/sources/bigtable/bigtable_test.go b/internal/sources/bigtable/bigtable_test.go index c3f2a7d3dc68..253f6e14ff51 100644 --- a/internal/sources/bigtable/bigtable_test.go +++ b/internal/sources/bigtable/bigtable_test.go @@ -15,9 +15,9 @@ package bigtable_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,16 +34,16 @@ func TestParseFromYamlBigtableDb(t *testing.T) { { desc: "can configure with a bigtable table", in: ` - sources: - my-bigtable-instance: - kind: bigtable - project: my-project - instance: my-instance + kind: sources + name: my-bigtable-instance + type: bigtable + project: my-project + instance: my-instance `, want: map[string]sources.SourceConfig{ "my-bigtable-instance": bigtable.Config{ Name: "my-bigtable-instance", - Kind: bigtable.SourceKind, + Type: bigtable.SourceType, Project: "my-project", Instance: "my-instance", }, @@ -52,16 +52,12 @@ func TestParseFromYamlBigtableDb(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -77,33 +73,29 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-bigtable-instance: - kind: bigtable - project: my-project - instance: my-instance - foo: bar + kind: sources + name: my-bigtable-instance + type: bigtable + project: my-project + instance: my-instance + foo: bar `, - err: "unable to parse source \"my-bigtable-instance\" as \"bigtable\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | instance: my-instance\n 3 | kind: bigtable\n 4 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-bigtable-instance\" as \"bigtable\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | instance: my-instance\n 3 | name: my-bigtable-instance\n 4 | project: my-project\n 5 | ", }, { desc: "missing required field", in: ` - sources: - my-bigtable-instance: - kind: bigtable - project: my-project + kind: sources + name: my-bigtable-instance + type: bigtable + project: my-project `, - err: "unable to parse source \"my-bigtable-instance\" as \"bigtable\": Key: 'Config.Instance' Error:Field validation for 'Instance' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-bigtable-instance\" as \"bigtable\": Key: 'Config.Instance' Error:Field validation for 'Instance' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cassandra/cassandra.go b/internal/sources/cassandra/cassandra.go index 49c070bf0658..44d8b362bcc6 100644 --- a/internal/sources/cassandra/cassandra.go +++ b/internal/sources/cassandra/cassandra.go @@ -25,11 +25,11 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "cassandra" +const SourceType string = "cassandra" func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -43,7 +43,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Hosts []string `yaml:"hosts" validate:"required"` Keyspace string `yaml:"keyspace"` ProtoVersion int `yaml:"protoVersion"` @@ -68,9 +68,9 @@ func (c Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.So return s, nil } -// SourceConfigKind implements sources.SourceConfig. -func (c Config) SourceConfigKind() string { - return SourceKind +// SourceConfigType implements sources.SourceConfig. +func (c Config) SourceConfigType() string { + return SourceType } var _ sources.SourceConfig = Config{} @@ -89,9 +89,9 @@ func (s *Source) ToConfig() sources.SourceConfig { return s.Config } -// SourceKind implements sources.Source. -func (s *Source) SourceKind() string { - return SourceKind +// SourceType implements sources.Source. +func (s *Source) SourceType() string { + return SourceType } func (s *Source) RunSQL(ctx context.Context, statement string, params parameters.ParamValues) (any, error) { @@ -120,7 +120,7 @@ var _ sources.Source = &Source{} func initCassandraSession(ctx context.Context, tracer trace.Tracer, c Config) (*gocql.Session, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, c.Name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, c.Name) defer span.End() // Validate authentication configuration diff --git a/internal/sources/cassandra/cassandra_test.go b/internal/sources/cassandra/cassandra_test.go index ddcbb3debead..e37e9c846ebe 100644 --- a/internal/sources/cassandra/cassandra_test.go +++ b/internal/sources/cassandra/cassandra_test.go @@ -15,11 +15,12 @@ package cassandra_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/cassandra" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,17 +34,17 @@ func TestParseFromYamlCassandra(t *testing.T) { { desc: "basic example (without optional fields)", in: ` - sources: - my-cassandra-instance: - kind: cassandra - hosts: - - "my-host1" - - "my-host2" + kind: sources + name: my-cassandra-instance + type: cassandra + hosts: + - "my-host1" + - "my-host2" `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-cassandra-instance": cassandra.Config{ Name: "my-cassandra-instance", - Kind: cassandra.SourceKind, + Type: cassandra.SourceType, Hosts: []string{"my-host1", "my-host2"}, Username: "", Password: "", @@ -59,25 +60,25 @@ func TestParseFromYamlCassandra(t *testing.T) { { desc: "with optional fields", in: ` - sources: - my-cassandra-instance: - kind: cassandra - hosts: - - "my-host1" - - "my-host2" - username: "user" - password: "pass" - keyspace: "example_keyspace" - protoVersion: 4 - caPath: "path/to/ca.crt" - certPath: "path/to/cert" - keyPath: "path/to/key" - enableHostVerification: true + kind: sources + name: my-cassandra-instance + type: cassandra + hosts: + - "my-host1" + - "my-host2" + username: "user" + password: "pass" + keyspace: "example_keyspace" + protoVersion: 4 + caPath: "path/to/ca.crt" + certPath: "path/to/cert" + keyPath: "path/to/key" + enableHostVerification: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-cassandra-instance": cassandra.Config{ Name: "my-cassandra-instance", - Kind: cassandra.SourceKind, + Type: cassandra.SourceType, Hosts: []string{"my-host1", "my-host2"}, Username: "user", Password: "pass", @@ -93,16 +94,12 @@ func TestParseFromYamlCassandra(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -118,33 +115,29 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-cassandra-instance: - kind: cassandra - hosts: - - "my-host" - foo: bar + kind: sources + name: my-cassandra-instance + type: cassandra + hosts: + - "my-host" + foo: bar `, - err: "unable to parse source \"my-cassandra-instance\" as \"cassandra\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | hosts:\n 3 | - my-host\n 4 | kind: cassandra", + err: "error unmarshaling sources: unable to parse source \"my-cassandra-instance\" as \"cassandra\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | hosts:\n 3 | - my-host\n 4 | name: my-cassandra-instance\n 5 | ", }, { desc: "missing required field", in: ` - sources: - my-cassandra-instance: - kind: cassandra + kind: sources + name: my-cassandra-instance + type: cassandra `, - err: "unable to parse source \"my-cassandra-instance\" as \"cassandra\": Key: 'Config.Hosts' Error:Field validation for 'Hosts' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-cassandra-instance\" as \"cassandra\": Key: 'Config.Hosts' Error:Field validation for 'Hosts' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/clickhouse/clickhouse.go b/internal/sources/clickhouse/clickhouse.go index 3f0b6f961b92..599522ec1b5c 100644 --- a/internal/sources/clickhouse/clickhouse.go +++ b/internal/sources/clickhouse/clickhouse.go @@ -28,14 +28,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "clickhouse" +const SourceType string = "clickhouse" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -49,7 +49,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` Database string `yaml:"database" validate:"required"` @@ -59,8 +59,8 @@ type Config struct { Secure bool `yaml:"secure"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -88,8 +88,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -174,7 +174,7 @@ func validateConfig(protocol string) error { func initClickHouseConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, protocol string, secure bool) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() if protocol == "" { diff --git a/internal/sources/clickhouse/clickhouse_test.go b/internal/sources/clickhouse/clickhouse_test.go index 7a1bd321ebba..59830d107b5e 100644 --- a/internal/sources/clickhouse/clickhouse_test.go +++ b/internal/sources/clickhouse/clickhouse_test.go @@ -21,137 +21,113 @@ import ( "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" + "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/testutils" "go.opentelemetry.io/otel" ) -func TestConfigSourceConfigKind(t *testing.T) { - config := Config{} - if config.SourceConfigKind() != SourceKind { - t.Errorf("Expected %s, got %s", SourceKind, config.SourceConfigKind()) - } -} - -func TestNewConfig(t *testing.T) { - tests := []struct { - name string - yaml string - expected Config +func TestParseFromYamlClickhouse(t *testing.T) { + tcs := []struct { + desc string + in string + want server.SourceConfigs }{ { - name: "all fields specified", - yaml: ` - name: test-clickhouse - kind: clickhouse - host: localhost - port: "8443" - user: default - password: "mypass" - database: mydb - protocol: https - secure: true - `, - expected: Config{ - Name: "test-clickhouse", - Kind: "clickhouse", - Host: "localhost", - Port: "8443", - User: "default", - Password: "mypass", - Database: "mydb", - Protocol: "https", - Secure: true, - }, - }, - { - name: "minimal configuration with defaults", - yaml: ` - name: minimal-clickhouse - kind: clickhouse - host: 127.0.0.1 - port: "8123" - user: testuser - database: testdb + desc: "all fields specified", + in: ` + kind: sources + name: test-clickhouse + type: clickhouse + host: localhost + port: "8443" + user: default + password: "mypass" + database: mydb + protocol: https + secure: true `, - expected: Config{ - Name: "minimal-clickhouse", - Kind: "clickhouse", - Host: "127.0.0.1", - Port: "8123", - User: "testuser", - Password: "", - Database: "testdb", - Protocol: "", - Secure: false, + want: map[string]sources.SourceConfig{ + "test-clickhouse": Config{ + Name: "test-clickhouse", + Type: "clickhouse", + Host: "localhost", + Port: "8443", + User: "default", + Password: "mypass", + Database: "mydb", + Protocol: "https", + Secure: true, + }, }, }, { - name: "http protocol", - yaml: ` - name: http-clickhouse - kind: clickhouse - host: clickhouse.example.com - port: "8123" - user: analytics - password: "securepass" - database: analytics_db - protocol: http - secure: false + desc: "minimal configuration with defaults", + in: ` + kind: sources + name: minimal-clickhouse + type: clickhouse + host: 127.0.0.1 + port: "8123" + user: testuser + database: testdb `, - expected: Config{ - Name: "http-clickhouse", - Kind: "clickhouse", - Host: "clickhouse.example.com", - Port: "8123", - User: "analytics", - Password: "securepass", - Database: "analytics_db", - Protocol: "http", - Secure: false, + want: map[string]sources.SourceConfig{ + "minimal-clickhouse": Config{ + Name: "minimal-clickhouse", + Type: "clickhouse", + Host: "127.0.0.1", + Port: "8123", + User: "testuser", + Password: "", + Database: "testdb", + Protocol: "", + Secure: false, + }, }, }, + } + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) + if err != nil { + t.Fatalf("unable to unmarshal: %s", err) + } + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) + } + }) + } +} + +func TestFailParseFromYaml(t *testing.T) { + tcs := []struct { + desc string + in string + err string + }{ { - name: "https with secure connection", - yaml: ` - name: secure-clickhouse - kind: clickhouse - host: secure.clickhouse.io - port: "8443" - user: secureuser - password: "verysecure" - database: production - protocol: https - secure: true + desc: "extra field", + in: ` + kind: sources + name: test-clickhouse + type: clickhouse + host: localhost + foo: bar `, - expected: Config{ - Name: "secure-clickhouse", - Kind: "clickhouse", - Host: "secure.clickhouse.io", - Port: "8443", - User: "secureuser", - Password: "verysecure", - Database: "production", - Protocol: "https", - Secure: true, - }, + err: "error unmarshaling sources: unable to parse source \"test-clickhouse\" as \"clickhouse\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | host: localhost\n 3 | name: test-clickhouse\n 4 | type: clickhouse", }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - decoder := yaml.NewDecoder(strings.NewReader(string(testutils.FormatYaml(tt.yaml)))) - config, err := newConfig(context.Background(), tt.expected.Name, decoder) - if err != nil { - t.Fatalf("Failed to create config: %v", err) - } - - clickhouseConfig, ok := config.(Config) - if !ok { - t.Fatalf("Expected Config type, got %T", config) + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) + if err == nil { + t.Fatalf("expect parsing to fail") } - - if diff := cmp.Diff(tt.expected, clickhouseConfig); diff != "" { - t.Errorf("Config mismatch (-want +got):\n%s", diff) + errStr := err.Error() + if errStr != tc.err { + t.Fatalf("unexpected error: got %q, want %q", errStr, tc.err) } }) } @@ -167,19 +143,11 @@ func TestNewConfigInvalidYAML(t *testing.T) { name: "invalid yaml syntax", yaml: ` name: test-clickhouse - kind: clickhouse + type: clickhouse host: [invalid `, expectError: true, }, - { - name: "missing required fields", - yaml: ` - name: test-clickhouse - kind: clickhouse - `, - expectError: false, - }, } for _, tt := range tests { @@ -196,10 +164,10 @@ func TestNewConfigInvalidYAML(t *testing.T) { } } -func TestSource_SourceKind(t *testing.T) { +func TestSource_SourceType(t *testing.T) { source := &Source{} - if source.SourceKind() != SourceKind { - t.Errorf("Expected %s, got %s", SourceKind, source.SourceKind()) + if source.SourceType() != SourceType { + t.Errorf("Expected %s, got %s", SourceType, source.SourceType()) } } diff --git a/internal/sources/cloudgda/cloud_gda.go b/internal/sources/cloudgda/cloud_gda.go index 5743991647d0..80e8df431c7c 100644 --- a/internal/sources/cloudgda/cloud_gda.go +++ b/internal/sources/cloudgda/cloud_gda.go @@ -29,15 +29,15 @@ import ( "golang.org/x/oauth2/google" ) -const SourceKind string = "cloud-gemini-data-analytics" +const SourceType string = "cloud-gemini-data-analytics" const Endpoint string = "https://geminidataanalytics.googleapis.com" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,13 +51,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` ProjectID string `yaml:"projectId" validate:"required"` UseClientOAuth bool `yaml:"useClientOAuth"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // Initialize initializes a Gemini Data Analytics Source instance. @@ -102,8 +102,8 @@ type Source struct { userAgent string } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/cloudgda/cloud_gda_test.go b/internal/sources/cloudgda/cloud_gda_test.go index 30b977729dc7..6ec771f60120 100644 --- a/internal/sources/cloudgda/cloud_gda_test.go +++ b/internal/sources/cloudgda/cloud_gda_test.go @@ -20,7 +20,6 @@ import ( "path/filepath" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -39,15 +38,15 @@ func TestParseFromYamlCloudGDA(t *testing.T) { { desc: "basic example", in: ` - sources: - my-gda-instance: - kind: cloud-gemini-data-analytics - projectId: test-project-id - `, + kind: sources + name: my-gda-instance + type: cloud-gemini-data-analytics + projectId: test-project-id + `, want: map[string]sources.SourceConfig{ "my-gda-instance": cloudgda.Config{ Name: "my-gda-instance", - Kind: cloudgda.SourceKind, + Type: cloudgda.SourceType, ProjectID: "test-project-id", UseClientOAuth: false, }, @@ -56,16 +55,16 @@ func TestParseFromYamlCloudGDA(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-gda-instance: - kind: cloud-gemini-data-analytics - projectId: another-project - useClientOAuth: true + kind: sources + name: my-gda-instance + type: cloud-gemini-data-analytics + projectId: another-project + useClientOAuth: true `, want: map[string]sources.SourceConfig{ "my-gda-instance": cloudgda.Config{ Name: "my-gda-instance", - Kind: cloudgda.SourceKind, + Type: cloudgda.SourceType, ProjectID: "another-project", UseClientOAuth: true, }, @@ -76,16 +75,12 @@ func TestParseFromYamlCloudGDA(t *testing.T) { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -101,22 +96,18 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "missing projectId", in: ` - sources: - my-gda-instance: - kind: cloud-gemini-data-analytics + kind: sources + name: my-gda-instance + type: cloud-gemini-data-analytics `, - err: "unable to parse source \"my-gda-instance\" as \"cloud-gemini-data-analytics\": Key: 'Config.ProjectID' Error:Field validation for 'ProjectID' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-gda-instance\" as \"cloud-gemini-data-analytics\": Key: 'Config.ProjectID' Error:Field validation for 'ProjectID' failed on the 'required' tag", }, } for _, tc := range tcs { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } @@ -153,12 +144,12 @@ func TestInitialize(t *testing.T) { }{ { desc: "initialize with ADC", - cfg: cloudgda.Config{Name: "test-gda", Kind: cloudgda.SourceKind, ProjectID: "test-proj"}, + cfg: cloudgda.Config{Name: "test-gda", Type: cloudgda.SourceType, ProjectID: "test-proj"}, wantClientOAuth: false, }, { desc: "initialize with client OAuth", - cfg: cloudgda.Config{Name: "test-gda-oauth", Kind: cloudgda.SourceKind, ProjectID: "test-proj", UseClientOAuth: true}, + cfg: cloudgda.Config{Name: "test-gda-oauth", Type: cloudgda.SourceType, ProjectID: "test-proj", UseClientOAuth: true}, wantClientOAuth: true, }, } diff --git a/internal/sources/cloudhealthcare/cloud_healthcare.go b/internal/sources/cloudhealthcare/cloud_healthcare.go index 82cfbd583e5a..b3c5e3ede852 100644 --- a/internal/sources/cloudhealthcare/cloud_healthcare.go +++ b/internal/sources/cloudhealthcare/cloud_healthcare.go @@ -34,7 +34,7 @@ import ( "google.golang.org/api/option" ) -const SourceKind string = "cloud-healthcare" +const SourceType string = "cloud-healthcare" // validate interface var _ sources.SourceConfig = Config{} @@ -42,8 +42,8 @@ var _ sources.SourceConfig = Config{} type HealthcareServiceCreator func(tokenString string) (*healthcare.Service, error) func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -58,7 +58,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // Healthcare configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Region string `yaml:"region" validate:"required"` Dataset string `yaml:"dataset" validate:"required"` @@ -67,8 +67,8 @@ type Config struct { UseClientOAuth bool `yaml:"useClientOAuth"` } -func (c Config) SourceConfigKind() string { - return SourceKind +func (c Config) SourceConfigType() string { + return SourceType } func (c Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -144,7 +144,7 @@ func newHealthcareServiceCreator(ctx context.Context, tracer trace.Tracer, name } func initHealthcareConnectionWithOAuthToken(ctx context.Context, tracer trace.Tracer, name string, userAgent string, tokenString string) (*healthcare.Service, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Construct token source token := &oauth2.Token{ @@ -162,7 +162,7 @@ func initHealthcareConnectionWithOAuthToken(ctx context.Context, tracer trace.Tr } func initHealthcareConnection(ctx context.Context, tracer trace.Tracer, name string) (*healthcare.Service, oauth2.TokenSource, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() cred, err := google.FindDefaultCredentials(ctx, healthcare.CloudHealthcareScope) @@ -194,8 +194,8 @@ type Source struct { allowedDICOMStores map[string]struct{} } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -517,14 +517,14 @@ func (s *Source) RetrieveRenderedDICOMInstance(storeID, study, series, sop strin return base64String, nil } -func (s *Source) SearchDICOM(toolKind, storeID, dicomWebPath, tokenStr string, opts []googleapi.CallOption) (any, error) { +func (s *Source) SearchDICOM(toolType, storeID, dicomWebPath, tokenStr string, opts []googleapi.CallOption) (any, error) { svc, err := s.getService(tokenStr) if err != nil { return nil, err } name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", s.Project(), s.Region(), s.DatasetID(), storeID) var resp *http.Response - switch toolKind { + switch toolType { case "cloud-healthcare-search-dicom-instances": resp, err = svc.Projects.Locations.Datasets.DicomStores.SearchForInstances(name, dicomWebPath).Do(opts...) case "cloud-healthcare-search-dicom-series": @@ -532,7 +532,7 @@ func (s *Source) SearchDICOM(toolKind, storeID, dicomWebPath, tokenStr string, o case "cloud-healthcare-search-dicom-studies": resp, err = svc.Projects.Locations.Datasets.DicomStores.SearchForStudies(name, dicomWebPath).Do(opts...) default: - return nil, fmt.Errorf("incompatible tool kind: %s", toolKind) + return nil, fmt.Errorf("incompatible tool type: %s", toolType) } if err != nil { return nil, fmt.Errorf("failed to search dicom series: %w", err) diff --git a/internal/sources/cloudhealthcare/cloud_healthcare_test.go b/internal/sources/cloudhealthcare/cloud_healthcare_test.go index 688a701cbad4..4d4e75c9aa67 100644 --- a/internal/sources/cloudhealthcare/cloud_healthcare_test.go +++ b/internal/sources/cloudhealthcare/cloud_healthcare_test.go @@ -15,11 +15,12 @@ package cloudhealthcare_test import ( + "context" "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/cloudhealthcare" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,17 +34,17 @@ func TestParseFromYamlCloudHealthcare(t *testing.T) { { desc: "basic example", in: ` - sources: - my-instance: - kind: cloud-healthcare - project: my-project - region: us-central1 - dataset: my-dataset + kind: sources + name: my-instance + type: cloud-healthcare + project: my-project + region: us-central1 + dataset: my-dataset `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudhealthcare.Config{ Name: "my-instance", - Kind: cloudhealthcare.SourceKind, + Type: cloudhealthcare.SourceType, Project: "my-project", Region: "us-central1", Dataset: "my-dataset", @@ -54,18 +55,18 @@ func TestParseFromYamlCloudHealthcare(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-instance: - kind: cloud-healthcare - project: my-project - region: us - dataset: my-dataset - useClientOAuth: true + kind: sources + name: my-instance + type: cloud-healthcare + project: my-project + region: us + dataset: my-dataset + useClientOAuth: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudhealthcare.Config{ Name: "my-instance", - Kind: cloudhealthcare.SourceKind, + Type: cloudhealthcare.SourceType, Project: "my-project", Region: "us", Dataset: "my-dataset", @@ -76,22 +77,22 @@ func TestParseFromYamlCloudHealthcare(t *testing.T) { { desc: "with allowed stores example", in: ` - sources: - my-instance: - kind: cloud-healthcare - project: my-project - region: us - dataset: my-dataset - allowedFhirStores: - - my-fhir-store - allowedDicomStores: - - my-dicom-store1 - - my-dicom-store2 + kind: sources + name: my-instance + type: cloud-healthcare + project: my-project + region: us + dataset: my-dataset + allowedFhirStores: + - my-fhir-store + allowedDicomStores: + - my-dicom-store1 + - my-dicom-store2 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudhealthcare.Config{ Name: "my-instance", - Kind: cloudhealthcare.SourceKind, + Type: cloudhealthcare.SourceType, Project: "my-project", Region: "us", Dataset: "my-dataset", @@ -103,16 +104,12 @@ func TestParseFromYamlCloudHealthcare(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -127,35 +124,31 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-instance: - kind: cloud-healthcare - project: my-project - region: us-central1 - dataset: my-dataset - foo: bar + kind: sources + name: my-instance + type: cloud-healthcare + project: my-project + region: us-central1 + dataset: my-dataset + foo: bar `, - err: "unable to parse source \"my-instance\" as \"cloud-healthcare\": [2:1] unknown field \"foo\"\n 1 | dataset: my-dataset\n> 2 | foo: bar\n ^\n 3 | kind: cloud-healthcare\n 4 | project: my-project\n 5 | region: us-central1", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"cloud-healthcare\": [2:1] unknown field \"foo\"\n 1 | dataset: my-dataset\n> 2 | foo: bar\n ^\n 3 | name: my-instance\n 4 | project: my-project\n 5 | region: us-central1\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-instance: - kind: cloud-healthcare - project: my-project - region: us-central1 + kind: sources + name: my-instance + type: cloud-healthcare + project: my-project + region: us-central1 `, - err: `unable to parse source "my-instance" as "cloud-healthcare": Key: 'Config.Dataset' Error:Field validation for 'Dataset' failed on the 'required' tag`, + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"cloud-healthcare\": Key: 'Config.Dataset' Error:Field validation for 'Dataset' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cloudmonitoring/cloud_monitoring.go b/internal/sources/cloudmonitoring/cloud_monitoring.go index eb478dce2412..e59204a7b60a 100644 --- a/internal/sources/cloudmonitoring/cloud_monitoring.go +++ b/internal/sources/cloudmonitoring/cloud_monitoring.go @@ -29,14 +29,14 @@ import ( monitoring "google.golang.org/api/monitoring/v3" ) -const SourceKind string = "cloud-monitoring" +const SourceType string = "cloud-monitoring" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,12 +50,12 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` UseClientOAuth bool `yaml:"useClientOAuth"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // Initialize initializes a Cloud Monitoring Source instance. @@ -99,8 +99,8 @@ type Source struct { userAgent string } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/cloudmonitoring/cloud_monitoring_test.go b/internal/sources/cloudmonitoring/cloud_monitoring_test.go index 329af6a2a441..cd9533929f70 100644 --- a/internal/sources/cloudmonitoring/cloud_monitoring_test.go +++ b/internal/sources/cloudmonitoring/cloud_monitoring_test.go @@ -15,9 +15,9 @@ package cloudmonitoring_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -35,14 +35,14 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { { desc: "basic example", in: ` - sources: - my-cloud-monitoring-instance: - kind: cloud-monitoring + kind: sources + name: my-cloud-monitoring-instance + type: cloud-monitoring `, want: map[string]sources.SourceConfig{ "my-cloud-monitoring-instance": cloudmonitoring.Config{ Name: "my-cloud-monitoring-instance", - Kind: cloudmonitoring.SourceKind, + Type: cloudmonitoring.SourceType, UseClientOAuth: false, }, }, @@ -50,15 +50,15 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-cloud-monitoring-instance: - kind: cloud-monitoring - useClientOAuth: true + kind: sources + name: my-cloud-monitoring-instance + type: cloud-monitoring + useClientOAuth: true `, want: map[string]sources.SourceConfig{ "my-cloud-monitoring-instance": cloudmonitoring.Config{ Name: "my-cloud-monitoring-instance", - Kind: cloudmonitoring.SourceKind, + Type: cloudmonitoring.SourceType, UseClientOAuth: true, }, }, @@ -68,16 +68,12 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -93,36 +89,28 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-cloud-monitoring-instance: - kind: cloud-monitoring - project: test-project + kind: sources + name: my-cloud-monitoring-instance + type: cloud-monitoring + project: test-project `, - err: `unable to parse source "my-cloud-monitoring-instance" as "cloud-monitoring": [2:1] unknown field "project" - 1 | kind: cloud-monitoring -> 2 | project: test-project - ^ -`, + err: "error unmarshaling sources: unable to parse source \"my-cloud-monitoring-instance\" as \"cloud-monitoring\": [2:1] unknown field \"project\"\n 1 | name: my-cloud-monitoring-instance\n> 2 | project: test-project\n ^\n 3 | type: cloud-monitoring", }, { desc: "missing required field", in: ` - sources: - my-cloud-monitoring-instance: - useClientOAuth: true + kind: sources + name: my-cloud-monitoring-instance + useClientOAuth: true `, - err: "missing 'kind' field for source \"my-cloud-monitoring-instance\"", + err: "error unmarshaling sources: missing 'type' field or it is not a string", }, } for _, tc := range tcs { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cloudsqladmin/cloud_sql_admin.go b/internal/sources/cloudsqladmin/cloud_sql_admin.go index 9e22f56aa199..9f8ea53e3065 100644 --- a/internal/sources/cloudsqladmin/cloud_sql_admin.go +++ b/internal/sources/cloudsqladmin/cloud_sql_admin.go @@ -35,7 +35,7 @@ import ( sqladmin "google.golang.org/api/sqladmin/v1" ) -const SourceKind string = "cloud-sql-admin" +const SourceType string = "cloud-sql-admin" var ( targetLinkRegex = regexp.MustCompile(`/projects/([^/]+)/instances/([^/]+)/databases/([^/]+)`) @@ -46,8 +46,8 @@ var ( var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -61,13 +61,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` DefaultProject string `yaml:"defaultProject"` UseClientOAuth bool `yaml:"useClientOAuth"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // Initialize initializes a CloudSQL Admin Source instance. @@ -114,8 +114,8 @@ type Source struct { Service *sqladmin.Service } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/cloudsqladmin/cloud_sql_admin_test.go b/internal/sources/cloudsqladmin/cloud_sql_admin_test.go index 4138a0a7c47f..f597de6c3720 100644 --- a/internal/sources/cloudsqladmin/cloud_sql_admin_test.go +++ b/internal/sources/cloudsqladmin/cloud_sql_admin_test.go @@ -15,9 +15,9 @@ package cloudsqladmin_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -35,14 +35,14 @@ func TestParseFromYamlCloudSQLAdmin(t *testing.T) { { desc: "basic example", in: ` - sources: - my-cloud-sql-admin-instance: - kind: cloud-sql-admin + kind: sources + name: my-cloud-sql-admin-instance + type: cloud-sql-admin `, want: map[string]sources.SourceConfig{ "my-cloud-sql-admin-instance": cloudsqladmin.Config{ Name: "my-cloud-sql-admin-instance", - Kind: cloudsqladmin.SourceKind, + Type: cloudsqladmin.SourceType, UseClientOAuth: false, }, }, @@ -50,15 +50,15 @@ func TestParseFromYamlCloudSQLAdmin(t *testing.T) { { desc: "use client auth example", in: ` - sources: - my-cloud-sql-admin-instance: - kind: cloud-sql-admin - useClientOAuth: true + kind: sources + name: my-cloud-sql-admin-instance + type: cloud-sql-admin + useClientOAuth: true `, want: map[string]sources.SourceConfig{ "my-cloud-sql-admin-instance": cloudsqladmin.Config{ Name: "my-cloud-sql-admin-instance", - Kind: cloudsqladmin.SourceKind, + Type: cloudsqladmin.SourceType, UseClientOAuth: true, }, }, @@ -68,16 +68,12 @@ func TestParseFromYamlCloudSQLAdmin(t *testing.T) { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -93,36 +89,28 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-cloud-sql-admin-instance: - kind: cloud-sql-admin - project: test-project + kind: sources + name: my-cloud-sql-admin-instance + type: cloud-sql-admin + project: test-project `, - err: `unable to parse source "my-cloud-sql-admin-instance" as "cloud-sql-admin": [2:1] unknown field "project" - 1 | kind: cloud-sql-admin -> 2 | project: test-project - ^ -`, + err: "error unmarshaling sources: unable to parse source \"my-cloud-sql-admin-instance\" as \"cloud-sql-admin\": [2:1] unknown field \"project\"\n 1 | name: my-cloud-sql-admin-instance\n> 2 | project: test-project\n ^\n 3 | type: cloud-sql-admin", }, { desc: "missing required field", in: ` - sources: - my-cloud-sql-admin-instance: - useClientOAuth: true + kind: sources + name: my-cloud-sql-admin-instance + useClientOAuth: true `, - err: "missing 'kind' field for source \"my-cloud-sql-admin-instance\"", + err: "error unmarshaling sources: missing 'type' field or it is not a string", }, } for _, tc := range tcs { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cloudsqlmssql/cloud_sql_mssql.go b/internal/sources/cloudsqlmssql/cloud_sql_mssql.go index 02480df326f4..9ea632b1bb96 100644 --- a/internal/sources/cloudsqlmssql/cloud_sql_mssql.go +++ b/internal/sources/cloudsqlmssql/cloud_sql_mssql.go @@ -29,14 +29,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "cloud-sql-mssql" +const SourceType string = "cloud-sql-mssql" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,7 +51,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // Cloud SQL MSSQL configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Region string `yaml:"region" validate:"required"` Instance string `yaml:"instance" validate:"required"` @@ -62,9 +62,9 @@ type Config struct { Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - // Returns Cloud SQL MSSQL source kind - return SourceKind +func (r Config) SourceConfigType() string { + // Returns Cloud SQL MSSQL source type + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -94,9 +94,9 @@ type Source struct { Db *sql.DB } -func (s *Source) SourceKind() string { - // Returns Cloud SQL MSSQL source kind - return SourceKind +func (s *Source) SourceType() string { + // Returns Cloud SQL MSSQL source type + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -152,7 +152,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initCloudSQLMssqlConnection(ctx context.Context, tracer trace.Tracer, name, project, region, instance, ipType, user, pass, dbname string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) diff --git a/internal/sources/cloudsqlmssql/cloud_sql_mssql_test.go b/internal/sources/cloudsqlmssql/cloud_sql_mssql_test.go index 4af46d63ca42..3f7b975d388f 100644 --- a/internal/sources/cloudsqlmssql/cloud_sql_mssql_test.go +++ b/internal/sources/cloudsqlmssql/cloud_sql_mssql_test.go @@ -15,11 +15,12 @@ package cloudsqlmssql_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlmssql" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,20 +34,20 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) { { desc: "basic example", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-instance + type: cloud-sql-mssql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudsqlmssql.Config{ Name: "my-instance", - Kind: cloudsqlmssql.SourceKind, + Type: cloudsqlmssql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -60,21 +61,21 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) { { desc: "psc ipType", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - ipType: psc + kind: sources + name: my-instance + type: cloud-sql-mssql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + ipType: psc `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudsqlmssql.Config{ Name: "my-instance", - Kind: cloudsqlmssql.SourceKind, + Type: cloudsqlmssql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -88,21 +89,21 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) { { desc: "with deprecated ipAddress", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - ipAddress: random - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-instance + type: cloud-sql-mssql + project: my-project + region: my-region + instance: my-instance + ipAddress: random + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": cloudsqlmssql.Config{ Name: "my-instance", - Kind: cloudsqlmssql.SourceKind, + Type: cloudsqlmssql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -117,16 +118,12 @@ func TestParseFromYamlCloudSQLMssql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect psarse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect psarse: want %v, got %v", tc.want, got) } }) } @@ -142,57 +139,53 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid ipType", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - ipType: fail - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-instance + type: cloud-sql-mssql + project: my-project + region: my-region + instance: my-instance + ipType: fail + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-instance\" as \"cloud-sql-mssql\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"cloud-sql-mssql\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", }, { desc: "extra field", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-instance + type: cloud-sql-mssql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-instance\" as \"cloud-sql-mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | kind: cloud-sql-mssql\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"cloud-sql-mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | name: my-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-instance: - kind: cloud-sql-mssql - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-instance + type: cloud-sql-mssql + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-instance\" as \"cloud-sql-mssql\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"cloud-sql-mssql\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cloudsqlmysql/cloud_sql_mysql.go b/internal/sources/cloudsqlmysql/cloud_sql_mysql.go index 759f00af7d93..648f817de416 100644 --- a/internal/sources/cloudsqlmysql/cloud_sql_mysql.go +++ b/internal/sources/cloudsqlmysql/cloud_sql_mysql.go @@ -30,14 +30,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "cloud-sql-mysql" +const SourceType string = "cloud-sql-mysql" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,7 +51,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Region string `yaml:"region" validate:"required"` Instance string `yaml:"instance" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -90,8 +90,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -184,7 +184,7 @@ func getConnectionConfig(ctx context.Context, user, pass string) (string, string func initCloudSQLMySQLConnectionPool(ctx context.Context, tracer trace.Tracer, name, project, region, instance, ipType, user, pass, dbname string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the driver to connect to the database diff --git a/internal/sources/cloudsqlmysql/cloud_sql_mysql_test.go b/internal/sources/cloudsqlmysql/cloud_sql_mysql_test.go index 74e9d9dd821f..9946abab0986 100644 --- a/internal/sources/cloudsqlmysql/cloud_sql_mysql_test.go +++ b/internal/sources/cloudsqlmysql/cloud_sql_mysql_test.go @@ -15,11 +15,12 @@ package cloudsqlmysql_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlmysql" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,20 +34,20 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "basic example", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -60,21 +61,21 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "public ipType", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: Public - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: Public + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -88,21 +89,21 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "private ipType", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: private - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: private + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -116,21 +117,21 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "psc ipType", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: psc - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: psc + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -144,16 +145,12 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -169,57 +166,53 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid ipType", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: fail - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: fail + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", }, { desc: "extra field", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | kind: cloud-sql-mysql\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | name: my-mysql-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"cloud-sql-mysql\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/cloudsqlpg/cloud_sql_pg.go b/internal/sources/cloudsqlpg/cloud_sql_pg.go index dc7e59be3d32..330976889270 100644 --- a/internal/sources/cloudsqlpg/cloud_sql_pg.go +++ b/internal/sources/cloudsqlpg/cloud_sql_pg.go @@ -28,14 +28,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "cloud-sql-postgres" +const SourceType string = "cloud-sql-postgres" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -49,7 +49,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Region string `yaml:"region" validate:"required"` Instance string `yaml:"instance" validate:"required"` @@ -59,8 +59,8 @@ type Config struct { Password string `yaml:"password"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -88,8 +88,8 @@ type Source struct { Pool *pgxpool.Pool } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -162,7 +162,7 @@ func getConnectionConfig(ctx context.Context, user, pass, dbname string) (string func initCloudSQLPgConnectionPool(ctx context.Context, tracer trace.Tracer, name, project, region, instance, ipType, user, pass, dbname string) (*pgxpool.Pool, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the driver to connect to the database diff --git a/internal/sources/cloudsqlpg/cloud_sql_pg_test.go b/internal/sources/cloudsqlpg/cloud_sql_pg_test.go index 0b833a94e082..2f0f0118d201 100644 --- a/internal/sources/cloudsqlpg/cloud_sql_pg_test.go +++ b/internal/sources/cloudsqlpg/cloud_sql_pg_test.go @@ -15,11 +15,12 @@ package cloudsqlpg_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlpg" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,20 +34,20 @@ func TestParseFromYamlCloudSQLPg(t *testing.T) { { desc: "basic example", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": cloudsqlpg.Config{ Name: "my-pg-instance", - Kind: cloudsqlpg.SourceKind, + Type: cloudsqlpg.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -60,21 +61,21 @@ func TestParseFromYamlCloudSQLPg(t *testing.T) { { desc: "public ipType", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - ipType: Public - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + ipType: Public + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": cloudsqlpg.Config{ Name: "my-pg-instance", - Kind: cloudsqlpg.SourceKind, + Type: cloudsqlpg.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -88,21 +89,21 @@ func TestParseFromYamlCloudSQLPg(t *testing.T) { { desc: "private ipType", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - ipType: private - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + ipType: private + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": cloudsqlpg.Config{ Name: "my-pg-instance", - Kind: cloudsqlpg.SourceKind, + Type: cloudsqlpg.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -116,21 +117,21 @@ func TestParseFromYamlCloudSQLPg(t *testing.T) { { desc: "psc ipType", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - ipType: psc - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + ipType: psc + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": cloudsqlpg.Config{ Name: "my-pg-instance", - Kind: cloudsqlpg.SourceKind, + Type: cloudsqlpg.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -144,16 +145,12 @@ func TestParseFromYamlCloudSQLPg(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -169,57 +166,53 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid ipType", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - ipType: fail - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + ipType: fail + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": ipType invalid: must be one of \"public\", \"private\", or \"psc\"", }, { desc: "extra field", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | kind: cloud-sql-postgres\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | name: my-pg-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-pg-instance: - kind: cloud-sql-postgres - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: cloud-sql-postgres + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"cloud-sql-postgres\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/couchbase/couchbase.go b/internal/sources/couchbase/couchbase.go index c273a47ec00b..222acb0f5ba6 100644 --- a/internal/sources/couchbase/couchbase.go +++ b/internal/sources/couchbase/couchbase.go @@ -29,14 +29,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "couchbase" +const SourceType string = "couchbase" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,7 +50,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` ConnectionString string `yaml:"connectionString" validate:"required"` Bucket string `yaml:"bucket" validate:"required"` Scope string `yaml:"scope" validate:"required"` @@ -66,8 +66,8 @@ type Config struct { QueryScanConsistency uint `yaml:"queryScanConsistency"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -96,8 +96,8 @@ type Source struct { Scope *gocb.Scope } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/couchbase/couchbase_test.go b/internal/sources/couchbase/couchbase_test.go index 43677333c4ce..3fb8efc03463 100644 --- a/internal/sources/couchbase/couchbase_test.go +++ b/internal/sources/couchbase/couchbase_test.go @@ -15,11 +15,12 @@ package couchbase_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/couchbase" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlCouchbase(t *testing.T) { { desc: "basic example", in: ` - sources: - my-couchbase-instance: - kind: couchbase - connectionString: localhost - username: Administrator - password: password - bucket: travel-sample - scope: inventory + kind: sources + name: my-couchbase-instance + type: couchbase + connectionString: localhost + username: Administrator + password: password + bucket: travel-sample + scope: inventory `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-couchbase-instance": couchbase.Config{ Name: "my-couchbase-instance", - Kind: couchbase.SourceKind, + Type: couchbase.SourceType, ConnectionString: "localhost", Username: "Administrator", Password: "password", @@ -57,24 +58,24 @@ func TestParseFromYamlCouchbase(t *testing.T) { { desc: "with TLS configuration", in: ` - sources: - my-couchbase-instance: - kind: couchbase - connectionString: couchbases://localhost - bucket: travel-sample - scope: inventory - clientCert: /path/to/cert.pem - clientKey: /path/to/key.pem - clientCertPassword: password - clientKeyPassword: password - caCert: /path/to/ca.pem - noSslVerify: false - queryScanConsistency: 2 + kind: sources + name: my-couchbase-instance + type: couchbase + connectionString: couchbases://localhost + bucket: travel-sample + scope: inventory + clientCert: /path/to/cert.pem + clientKey: /path/to/key.pem + clientCertPassword: password + clientKeyPassword: password + caCert: /path/to/ca.pem + noSslVerify: false + queryScanConsistency: 2 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-couchbase-instance": couchbase.Config{ Name: "my-couchbase-instance", - Kind: couchbase.SourceKind, + Type: couchbase.SourceType, ConnectionString: "couchbases://localhost", Bucket: "travel-sample", Scope: "inventory", @@ -91,16 +92,12 @@ func TestParseFromYamlCouchbase(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -115,39 +112,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-couchbase-instance: - kind: couchbase - connectionString: localhost - username: Administrator - password: password - bucket: travel-sample - scope: inventory - foo: bar + kind: sources + name: my-couchbase-instance + type: couchbase + connectionString: localhost + username: Administrator + password: password + bucket: travel-sample + scope: inventory + foo: bar `, - err: "unable to parse source \"my-couchbase-instance\" as \"couchbase\": [3:1] unknown field \"foo\"\n 1 | bucket: travel-sample\n 2 | connectionString: localhost\n> 3 | foo: bar\n ^\n 4 | kind: couchbase\n 5 | password: password\n 6 | scope: inventory\n 7 | ", + err: "error unmarshaling sources: unable to parse source \"my-couchbase-instance\" as \"couchbase\": [3:1] unknown field \"foo\"\n 1 | bucket: travel-sample\n 2 | connectionString: localhost\n> 3 | foo: bar\n ^\n 4 | name: my-couchbase-instance\n 5 | password: password\n 6 | scope: inventory\n 7 | ", }, { desc: "missing required field", in: ` - sources: - my-couchbase-instance: - kind: couchbase - username: Administrator - password: password - bucket: travel-sample - scope: inventory + kind: sources + name: my-couchbase-instance + type: couchbase + username: Administrator + password: password + bucket: travel-sample + scope: inventory `, - err: "unable to parse source \"my-couchbase-instance\" as \"couchbase\": Key: 'Config.ConnectionString' Error:Field validation for 'ConnectionString' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-couchbase-instance\" as \"couchbase\": Key: 'Config.ConnectionString' Error:Field validation for 'ConnectionString' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/dataplex/dataplex.go b/internal/sources/dataplex/dataplex.go index 52d64b194d90..3ddeb2ec9f90 100644 --- a/internal/sources/dataplex/dataplex.go +++ b/internal/sources/dataplex/dataplex.go @@ -31,14 +31,14 @@ import ( grpcstatus "google.golang.org/grpc/status" ) -const SourceKind string = "dataplex" +const SourceType string = "dataplex" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -53,13 +53,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // Dataplex configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` } -func (r Config) SourceConfigKind() string { - // Returns Dataplex source kind - return SourceKind +func (r Config) SourceConfigType() string { + // Returns Dataplex source type + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -83,9 +83,9 @@ type Source struct { Client *dataplexapi.CatalogClient } -func (s *Source) SourceKind() string { - // Returns Dataplex source kind - return SourceKind +func (s *Source) SourceType() string { + // Returns Dataplex source type + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -106,7 +106,7 @@ func initDataplexConnection( name string, project string, ) (*dataplexapi.CatalogClient, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() cred, err := google.FindDefaultCredentials(ctx) diff --git a/internal/sources/dataplex/dataplex_test.go b/internal/sources/dataplex/dataplex_test.go index 0379eba5b4a6..10b9641c6bd1 100644 --- a/internal/sources/dataplex/dataplex_test.go +++ b/internal/sources/dataplex/dataplex_test.go @@ -15,11 +15,12 @@ package dataplex_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/dataplex" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,15 +34,15 @@ func TestParseFromYamlDataplex(t *testing.T) { { desc: "basic example", in: ` - sources: - my-instance: - kind: dataplex - project: my-project + kind: sources + name: my-instance + type: dataplex + project: my-project `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": dataplex.Config{ Name: "my-instance", - Kind: dataplex.SourceKind, + Type: dataplex.SourceType, Project: "my-project", }, }, @@ -49,16 +50,12 @@ func TestParseFromYamlDataplex(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -74,31 +71,27 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-instance: - kind: dataplex - project: my-project - foo: bar + kind: sources + name: my-instance + type: dataplex + project: my-project + foo: bar `, - err: "unable to parse source \"my-instance\" as \"dataplex\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | kind: dataplex\n 3 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"dataplex\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | name: my-instance\n 3 | project: my-project\n 4 | type: dataplex", }, { desc: "missing required field", in: ` - sources: - my-instance: - kind: dataplex + kind: sources + name: my-instance + type: dataplex `, - err: "unable to parse source \"my-instance\" as \"dataplex\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"dataplex\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/dgraph/dgraph.go b/internal/sources/dgraph/dgraph.go index 317779db381b..db2bc88d1fc6 100644 --- a/internal/sources/dgraph/dgraph.go +++ b/internal/sources/dgraph/dgraph.go @@ -30,14 +30,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "dgraph" +const SourceType string = "dgraph" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -67,7 +67,7 @@ type DgraphClient struct { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` DgraphUrl string `yaml:"dgraphUrl" validate:"required"` User string `yaml:"user"` Password string `yaml:"password"` @@ -75,8 +75,8 @@ type Config struct { ApiKey string `yaml:"apiKey"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -103,8 +103,8 @@ type Source struct { Client *DgraphClient `yaml:"client"` } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -139,7 +139,7 @@ func (s *Source) RunSQL(statement string, params parameters.ParamValues, isQuery func initDgraphHttpClient(ctx context.Context, tracer trace.Tracer, r Config) (*DgraphClient, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, r.Name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, r.Name) defer span.End() if r.DgraphUrl == "" { diff --git a/internal/sources/dgraph/dgraph_test.go b/internal/sources/dgraph/dgraph_test.go index d2db00668373..4681c0278e26 100644 --- a/internal/sources/dgraph/dgraph_test.go +++ b/internal/sources/dgraph/dgraph_test.go @@ -15,11 +15,12 @@ package dgraph_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/dgraph" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlDgraph(t *testing.T) { { desc: "basic example", in: ` - sources: - my-dgraph-instance: - kind: dgraph - dgraphUrl: https://localhost:8080 - apiKey: abc123 - password: pass@123 - namespace: 0 - user: user123 + kind: sources + name: my-dgraph-instance + type: dgraph + dgraphUrl: https://localhost:8080 + apiKey: abc123 + password: pass@123 + namespace: 0 + user: user123 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-dgraph-instance": dgraph.Config{ Name: "my-dgraph-instance", - Kind: dgraph.SourceKind, + Type: dgraph.SourceType, DgraphUrl: "https://localhost:8080", ApiKey: "abc123", Password: "pass@123", @@ -57,15 +58,15 @@ func TestParseFromYamlDgraph(t *testing.T) { { desc: "basic example minimal field", in: ` - sources: - my-dgraph-instance: - kind: dgraph - dgraphUrl: https://localhost:8080 + kind: sources + name: my-dgraph-instance + type: dgraph + dgraphUrl: https://localhost:8080 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-dgraph-instance": dgraph.Config{ Name: "my-dgraph-instance", - Kind: dgraph.SourceKind, + Type: dgraph.SourceType, DgraphUrl: "https://localhost:8080", }, }, @@ -74,16 +75,12 @@ func TestParseFromYamlDgraph(t *testing.T) { for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Sources); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -100,31 +97,27 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-dgraph-instance: - kind: dgraph - dgraphUrl: https://localhost:8080 - foo: bar + kind: sources + name: my-dgraph-instance + type: dgraph + dgraphUrl: https://localhost:8080 + foo: bar `, - err: "unable to parse source \"my-dgraph-instance\" as \"dgraph\": [2:1] unknown field \"foo\"\n 1 | dgraphUrl: https://localhost:8080\n> 2 | foo: bar\n ^\n 3 | kind: dgraph", + err: "error unmarshaling sources: unable to parse source \"my-dgraph-instance\" as \"dgraph\": [2:1] unknown field \"foo\"\n 1 | dgraphUrl: https://localhost:8080\n> 2 | foo: bar\n ^\n 3 | name: my-dgraph-instance\n 4 | type: dgraph", }, { desc: "missing required field", in: ` - sources: - my-dgraph-instance: - kind: dgraph + kind: sources + name: my-dgraph-instance + type: dgraph `, - err: "unable to parse source \"my-dgraph-instance\" as \"dgraph\": Key: 'Config.DgraphUrl' Error:Field validation for 'DgraphUrl' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-dgraph-instance\" as \"dgraph\": Key: 'Config.DgraphUrl' Error:Field validation for 'DgraphUrl' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/elasticsearch/elasticsearch.go b/internal/sources/elasticsearch/elasticsearch.go index b5ec915c18d3..42dd835b2335 100644 --- a/internal/sources/elasticsearch/elasticsearch.go +++ b/internal/sources/elasticsearch/elasticsearch.go @@ -30,14 +30,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "elasticsearch" +const SourceType string = "elasticsearch" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,15 +51,15 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Addresses []string `yaml:"addresses" validate:"required"` Username string `yaml:"username"` Password string `yaml:"password"` APIKey string `yaml:"apikey"` } -func (c Config) SourceConfigKind() string { - return SourceKind +func (c Config) SourceConfigType() string { + return SourceType } type EsClient interface { @@ -139,9 +139,9 @@ func (c Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.So return s, nil } -// SourceKind returns the kind string for this source. -func (s *Source) SourceKind() string { - return SourceKind +// SourceType returns the resourceType string for this source. +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/elasticsearch/elasticsearch_test.go b/internal/sources/elasticsearch/elasticsearch_test.go index 95d941edc462..d3170741f680 100644 --- a/internal/sources/elasticsearch/elasticsearch_test.go +++ b/internal/sources/elasticsearch/elasticsearch_test.go @@ -15,13 +15,15 @@ package elasticsearch_test import ( + "context" "reflect" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/elasticsearch" + "github.com/googleapis/genai-toolbox/internal/testutils" ) func TestParseFromYamlElasticsearch(t *testing.T) { @@ -33,17 +35,17 @@ func TestParseFromYamlElasticsearch(t *testing.T) { { desc: "basic example", in: ` - sources: - my-es-instance: - kind: elasticsearch - addresses: - - http://localhost:9200 - apikey: somekey - `, - want: server.SourceConfigs{ + kind: sources + name: my-es-instance + type: elasticsearch + addresses: + - http://localhost:9200 + apikey: somekey + `, + want: map[string]sources.SourceConfig{ "my-es-instance": elasticsearch.Config{ Name: "my-es-instance", - Kind: elasticsearch.SourceKind, + Type: elasticsearch.SourceType, Addresses: []string{"http://localhost:9200"}, APIKey: "somekey", }, @@ -52,20 +54,50 @@ func TestParseFromYamlElasticsearch(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - err := yaml.Unmarshal([]byte(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("failed to parse yaml: %v", err) } - if diff := cmp.Diff(tc.want, got.Sources); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Errorf("unexpected config diff (-want +got):\n%s", diff) } }) } } +func TestFailParseFromYaml(t *testing.T) { + tcs := []struct { + desc string + in string + err string + }{ + { + desc: "extra field", + in: ` + kind: sources + name: my-es-instance + type: elasticsearch + addresses: + - http://localhost:9200 + foo: bar + `, + err: "error unmarshaling sources: unable to parse source \"my-es-instance\" as \"elasticsearch\": [3:1] unknown field \"foo\"\n 1 | addresses:\n 2 | - http://localhost:9200\n> 3 | foo: bar\n ^\n 4 | name: my-es-instance\n 5 | type: elasticsearch", + }, + } + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) + if err == nil { + t.Fatalf("expect parsing to fail") + } + errStr := err.Error() + if errStr != tc.err { + t.Fatalf("unexpected error: got %q, want %q", errStr, tc.err) + } + }) + } +} + func TestTool_esqlToMap(t1 *testing.T) { tests := []struct { name string diff --git a/internal/sources/firebird/firebird.go b/internal/sources/firebird/firebird.go index 4be3d20cac54..1d3f22422781 100644 --- a/internal/sources/firebird/firebird.go +++ b/internal/sources/firebird/firebird.go @@ -27,13 +27,13 @@ import ( "github.com/googleapis/genai-toolbox/internal/sources" ) -const SourceKind string = "firebird" +const SourceType string = "firebird" var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -47,7 +47,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -55,8 +55,8 @@ type Config struct { Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -84,8 +84,8 @@ type Source struct { Db *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -144,7 +144,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an } func initFirebirdConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname string) (*sql.DB, error) { - _, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + _, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // urlExample := "user:password@host:port/path/to/database.fdb" diff --git a/internal/sources/firebird/firebird_test.go b/internal/sources/firebird/firebird_test.go index 0a7e72f66c10..71353517a872 100644 --- a/internal/sources/firebird/firebird_test.go +++ b/internal/sources/firebird/firebird_test.go @@ -15,11 +15,12 @@ package firebird_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/firebird" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlFirebird(t *testing.T) { { desc: "basic example", in: ` - sources: - my-fdb-instance: - kind: firebird - host: my-host - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-fdb-instance + type: firebird + host: my-host + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-fdb-instance": firebird.Config{ Name: "my-fdb-instance", - Kind: firebird.SourceKind, + Type: firebird.SourceType, Host: "my-host", Port: "my-port", Database: "my_db", @@ -57,16 +58,12 @@ func TestParseFromYamlFirebird(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -82,39 +79,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-fdb-instance: - kind: firebird - host: my-host - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-fdb-instance + type: firebird + host: my-host + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-fdb-instance\" as \"firebird\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: my-host\n 4 | kind: firebird\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-fdb-instance\" as \"firebird\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: my-host\n 4 | name: my-fdb-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-fdb-instance: - kind: firebird - host: my-host - port: my-port - database: my_db - user: my_user + kind: sources + name: my-fdb-instance + type: firebird + host: my-host + port: my-port + database: my_db + user: my_user `, - err: "unable to parse source \"my-fdb-instance\" as \"firebird\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-fdb-instance\" as \"firebird\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/firestore/firestore.go b/internal/sources/firestore/firestore.go index be9f7aa94f5d..0756f146a2e3 100644 --- a/internal/sources/firestore/firestore.go +++ b/internal/sources/firestore/firestore.go @@ -31,14 +31,14 @@ import ( "google.golang.org/genproto/googleapis/type/latlng" ) -const SourceKind string = "firestore" +const SourceType string = "firestore" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -53,14 +53,14 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // Firestore configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Database string `yaml:"database"` // Optional, defaults to "(default)" } -func (r Config) SourceConfigKind() string { - // Returns Firestore source kind - return SourceKind +func (r Config) SourceConfigType() string { + // Returns Firestore source type + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -92,9 +92,9 @@ type Source struct { RulesClient *firebaserules.Service } -func (s *Source) SourceKind() string { - // Returns Firestore source kind - return SourceKind +func (s *Source) SourceType() string { + // Returns Firestore source type + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -594,7 +594,7 @@ func initFirestoreConnection( project string, database string, ) (*firestore.Client, error) { - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) diff --git a/internal/sources/firestore/firestore_test.go b/internal/sources/firestore/firestore_test.go index 3f15440f133c..b65926bda30e 100644 --- a/internal/sources/firestore/firestore_test.go +++ b/internal/sources/firestore/firestore_test.go @@ -15,12 +15,13 @@ package firestore_test import ( + "context" "testing" "time" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/firestore" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -34,15 +35,15 @@ func TestParseFromYamlFirestore(t *testing.T) { { desc: "basic example with default database", in: ` - sources: - my-firestore: - kind: firestore - project: my-project + kind: sources + name: my-firestore + type: firestore + project: my-project `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-firestore": firestore.Config{ Name: "my-firestore", - Kind: firestore.SourceKind, + Type: firestore.SourceType, Project: "my-project", Database: "", }, @@ -51,16 +52,16 @@ func TestParseFromYamlFirestore(t *testing.T) { { desc: "with custom database", in: ` - sources: - my-firestore: - kind: firestore - project: my-project - database: my-database + kind: sources + name: my-firestore + type: firestore + project: my-project + database: my-database `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-firestore": firestore.Config{ Name: "my-firestore", - Kind: firestore.SourceKind, + Type: firestore.SourceType, Project: "my-project", Database: "my-database", }, @@ -69,22 +70,18 @@ func TestParseFromYamlFirestore(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } } -func TestFailParseFromYamlFirestore(t *testing.T) { +func TestFailParseFromYaml(t *testing.T) { tcs := []struct { desc string in string @@ -93,32 +90,27 @@ func TestFailParseFromYamlFirestore(t *testing.T) { { desc: "extra field", in: ` - sources: - my-firestore: - kind: firestore - project: my-project - foo: bar + kind: sources + name: my-firestore + type: firestore + project: my-project + foo: bar `, - err: "unable to parse source \"my-firestore\" as \"firestore\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | kind: firestore\n 3 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-firestore\" as \"firestore\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | name: my-firestore\n 3 | project: my-project\n 4 | type: firestore", }, { desc: "missing required field", in: ` - sources: - my-firestore: - kind: firestore - database: my-database + kind: sources + name: my-firestore + type: firestore `, - err: "unable to parse source \"my-firestore\" as \"firestore\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-firestore\" as \"firestore\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/http/http.go b/internal/sources/http/http.go index 238c19b60744..8a6d58a61926 100644 --- a/internal/sources/http/http.go +++ b/internal/sources/http/http.go @@ -29,14 +29,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "http" +const SourceType string = "http" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,7 +50,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` BaseURL string `yaml:"baseUrl"` Timeout string `yaml:"timeout"` DefaultHeaders map[string]string `yaml:"headers"` @@ -58,8 +58,8 @@ type Config struct { DisableSslVerification bool `yaml:"disableSslVerification"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // Initialize initializes an HTTP Source instance. @@ -122,8 +122,8 @@ type Source struct { client *http.Client } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/http/http_test.go b/internal/sources/http/http_test.go index 02d8fc6b4d5f..4332b24fcae6 100644 --- a/internal/sources/http/http_test.go +++ b/internal/sources/http/http_test.go @@ -15,9 +15,9 @@ package http_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,15 +34,15 @@ func TestParseFromYamlHttp(t *testing.T) { { desc: "basic example", in: ` - sources: - my-http-instance: - kind: http - baseUrl: http://test_server/ + kind: sources + name: my-http-instance + type: http + baseUrl: http://test_server/ `, want: map[string]sources.SourceConfig{ "my-http-instance": http.Config{ Name: "my-http-instance", - Kind: http.SourceKind, + Type: http.SourceType, BaseURL: "http://test_server/", Timeout: "30s", DisableSslVerification: false, @@ -52,23 +52,23 @@ func TestParseFromYamlHttp(t *testing.T) { { desc: "advanced example", in: ` - sources: - my-http-instance: - kind: http - baseUrl: http://test_server/ - timeout: 10s - headers: - Authorization: test_header - Custom-Header: custom - queryParams: - api-key: test_api_key - param: param-value - disableSslVerification: true + kind: sources + name: my-http-instance + type: http + baseUrl: http://test_server/ + timeout: 10s + headers: + Authorization: test_header + Custom-Header: custom + queryParams: + api-key: test_api_key + param: param-value + disableSslVerification: true `, want: map[string]sources.SourceConfig{ "my-http-instance": http.Config{ Name: "my-http-instance", - Kind: http.SourceKind, + Type: http.SourceType, BaseURL: "http://test_server/", Timeout: "10s", DefaultHeaders: map[string]string{"Authorization": "test_header", "Custom-Header": "custom"}, @@ -80,16 +80,12 @@ func TestParseFromYamlHttp(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -104,36 +100,32 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-http-instance: - kind: http - baseUrl: http://test_server/ - timeout: 10s - headers: - Authorization: test_header - queryParams: - api-key: test_api_key - project: test-project + kind: sources + name: my-http-instance + type: http + baseUrl: http://test_server/ + timeout: 10s + headers: + Authorization: test_header + queryParams: + api-key: test_api_key + project: test-project `, - err: "unable to parse source \"my-http-instance\" as \"http\": [5:1] unknown field \"project\"\n 2 | headers:\n 3 | Authorization: test_header\n 4 | kind: http\n> 5 | project: test-project\n ^\n 6 | queryParams:\n 7 | api-key: test_api_key\n 8 | timeout: 10s", + err: "error unmarshaling sources: unable to parse source \"my-http-instance\" as \"http\": [5:1] unknown field \"project\"\n 2 | headers:\n 3 | Authorization: test_header\n 4 | name: my-http-instance\n> 5 | project: test-project\n ^\n 6 | queryParams:\n 7 | api-key: test_api_key\n 8 | timeout: 10s\n 9 | ", }, { desc: "missing required field", in: ` - sources: - my-http-instance: - baseUrl: http://test_server/ + kind: sources + name: my-http-instance + baseUrl: http://test_server/ `, - err: "missing 'kind' field for source \"my-http-instance\"", + err: "error unmarshaling sources: missing 'type' field or it is not a string", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/looker/looker.go b/internal/sources/looker/looker.go index c7b401b08013..e20ec2107d68 100644 --- a/internal/sources/looker/looker.go +++ b/internal/sources/looker/looker.go @@ -33,14 +33,14 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const SourceKind string = "looker" +const SourceType string = "looker" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -64,7 +64,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` BaseURL string `yaml:"base_url" validate:"required"` ClientId string `yaml:"client_id"` ClientSecret string `yaml:"client_secret"` @@ -79,8 +79,8 @@ type Config struct { SessionLength int64 `yaml:"sessionLength"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // Initialize initializes a Looker Source instance. @@ -154,8 +154,8 @@ type Source struct { AuthTokenHeaderName string } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/looker/looker_test.go b/internal/sources/looker/looker_test.go index bd470f01303e..95fbf442f357 100644 --- a/internal/sources/looker/looker_test.go +++ b/internal/sources/looker/looker_test.go @@ -15,9 +15,9 @@ package looker_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,17 +34,17 @@ func TestParseFromYamlLooker(t *testing.T) { { desc: "basic example", in: ` - sources: - my-looker-instance: - kind: looker - base_url: http://example.looker.com/ - client_id: jasdl;k;tjl - client_secret: sdakl;jgflkasdfkfg + kind: sources + name: my-looker-instance + type: looker + base_url: http://example.looker.com/ + client_id: jasdl;k;tjl + client_secret: sdakl;jgflkasdfkfg `, want: map[string]sources.SourceConfig{ "my-looker-instance": looker.Config{ Name: "my-looker-instance", - Kind: looker.SourceKind, + Type: looker.SourceType, BaseURL: "http://example.looker.com/", ClientId: "jasdl;k;tjl", ClientSecret: "sdakl;jgflkasdfkfg", @@ -62,22 +62,18 @@ func TestParseFromYamlLooker(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } } -func TestFailParseFromYamlLooker(t *testing.T) { +func TestFailParseFromYaml(t *testing.T) { tcs := []struct { desc string in string @@ -86,34 +82,30 @@ func TestFailParseFromYamlLooker(t *testing.T) { { desc: "extra field", in: ` - sources: - my-looker-instance: - kind: looker - base_url: http://example.looker.com/ - client_id: jasdl;k;tjl - client_secret: sdakl;jgflkasdfkfg - schema: test-schema + kind: sources + name: my-looker-instance + type: looker + base_url: http://example.looker.com/ + client_id: jasdl;k;tjl + client_secret: sdakl;jgflkasdfkfg + schema: test-schema `, - err: "unable to parse source \"my-looker-instance\" as \"looker\": [5:1] unknown field \"schema\"\n 2 | client_id: jasdl;k;tjl\n 3 | client_secret: sdakl;jgflkasdfkfg\n 4 | kind: looker\n> 5 | schema: test-schema\n ^\n", + err: "error unmarshaling sources: unable to parse source \"my-looker-instance\" as \"looker\": [5:1] unknown field \"schema\"\n 2 | client_id: jasdl;k;tjl\n 3 | client_secret: sdakl;jgflkasdfkfg\n 4 | name: my-looker-instance\n> 5 | schema: test-schema\n ^\n 6 | type: looker", }, { desc: "missing required field", in: ` - sources: - my-looker-instance: - kind: looker - client_id: jasdl;k;tjl + kind: sources + name: my-looker-instance + type: looker + client_id: jasdl;k;tjl `, - err: "unable to parse source \"my-looker-instance\" as \"looker\": Key: 'Config.BaseURL' Error:Field validation for 'BaseURL' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-looker-instance\" as \"looker\": Key: 'Config.BaseURL' Error:Field validation for 'BaseURL' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/mindsdb/mindsdb.go b/internal/sources/mindsdb/mindsdb.go index 4bb5daac1c5c..8fde3b62221c 100644 --- a/internal/sources/mindsdb/mindsdb.go +++ b/internal/sources/mindsdb/mindsdb.go @@ -27,14 +27,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "mindsdb" +const SourceType string = "mindsdb" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -48,7 +48,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -57,8 +57,8 @@ type Config struct { QueryTimeout string `yaml:"queryTimeout"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -86,8 +86,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -159,7 +159,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initMindsDBConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, queryTimeout string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the driver to connect to the database diff --git a/internal/sources/mindsdb/mindsdb_test.go b/internal/sources/mindsdb/mindsdb_test.go index b80f0bc5a694..9195aa0c1fc4 100644 --- a/internal/sources/mindsdb/mindsdb_test.go +++ b/internal/sources/mindsdb/mindsdb_test.go @@ -15,11 +15,12 @@ package mindsdb_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/mindsdb" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlMindsDB(t *testing.T) { { desc: "basic example", in: ` - sources: - my-mindsdb-instance: - kind: mindsdb - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mindsdb-instance + type: mindsdb + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mindsdb-instance": mindsdb.Config{ Name: "my-mindsdb-instance", - Kind: mindsdb.SourceKind, + Type: mindsdb.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -57,20 +58,20 @@ func TestParseFromYamlMindsDB(t *testing.T) { { desc: "with query timeout", in: ` - sources: - my-mindsdb-instance: - kind: mindsdb - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - queryTimeout: 45s + kind: sources + name: my-mindsdb-instance + type: mindsdb + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + queryTimeout: 45s `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mindsdb-instance": mindsdb.Config{ Name: "my-mindsdb-instance", - Kind: mindsdb.SourceKind, + Type: mindsdb.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -83,16 +84,12 @@ func TestParseFromYamlMindsDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -108,39 +105,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-mindsdb-instance: - kind: mindsdb - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-mindsdb-instance + type: mindsdb + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-mindsdb-instance\" as \"mindsdb\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | kind: mindsdb\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-mindsdb-instance\" as \"mindsdb\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-mindsdb-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-mindsdb-instance: - kind: mindsdb - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mindsdb-instance + type: mindsdb + port: my-port + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-mindsdb-instance\" as \"mindsdb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-mindsdb-instance\" as \"mindsdb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/mongodb/mongodb.go b/internal/sources/mongodb/mongodb.go index 533e5005d58b..297da86c242a 100644 --- a/internal/sources/mongodb/mongodb.go +++ b/internal/sources/mongodb/mongodb.go @@ -29,14 +29,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "mongodb" +const SourceType string = "mongodb" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,12 +50,12 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Uri string `yaml:"uri" validate:"required"` // MongoDB Atlas connection URI } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -84,8 +84,8 @@ type Source struct { Client *mongo.Client } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -293,7 +293,7 @@ func (s *Source) DeleteOne(ctx context.Context, filterString, database, collecti func initMongoDBClient(ctx context.Context, tracer trace.Tracer, name, uri string) (*mongo.Client, error) { // Start a tracing span - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) diff --git a/internal/sources/mongodb/mongodb_test.go b/internal/sources/mongodb/mongodb_test.go index 0c882899a449..9fec7ecc7476 100644 --- a/internal/sources/mongodb/mongodb_test.go +++ b/internal/sources/mongodb/mongodb_test.go @@ -15,11 +15,12 @@ package mongodb_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/mongodb" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,15 +34,15 @@ func TestParseFromYamlMongoDB(t *testing.T) { { desc: "basic example", in: ` - sources: - mongo-db: - kind: "mongodb" - uri: "mongodb+srv://username:password@host/dbname" + kind: sources + name: mongo-db + type: "mongodb" + uri: "mongodb+srv://username:password@host/dbname" `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "mongo-db": mongodb.Config{ Name: "mongo-db", - Kind: mongodb.SourceKind, + Type: mongodb.SourceType, Uri: "mongodb+srv://username:password@host/dbname", }, }, @@ -49,16 +50,12 @@ func TestParseFromYamlMongoDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -74,31 +71,27 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - mongo-db: - kind: mongodb - uri: "mongodb+srv://username:password@host/dbname" - foo: bar + kind: sources + name: mongo-db + type: mongodb + uri: "mongodb+srv://username:password@host/dbname" + foo: bar `, - err: "unable to parse source \"mongo-db\" as \"mongodb\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | kind: mongodb\n 3 | uri: mongodb+srv://username:password@host/dbname", + err: "error unmarshaling sources: unable to parse source \"mongo-db\" as \"mongodb\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | name: mongo-db\n 3 | type: mongodb\n 4 | uri: mongodb+srv://username:password@host/dbname", }, { desc: "missing required field", in: ` - sources: - mongo-db: - kind: mongodb + kind: sources + name: mongo-db + type: mongodb `, - err: "unable to parse source \"mongo-db\" as \"mongodb\": Key: 'Config.Uri' Error:Field validation for 'Uri' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"mongo-db\" as \"mongodb\": Key: 'Config.Uri' Error:Field validation for 'Uri' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/mssql/mssql.go b/internal/sources/mssql/mssql.go index 688ccf18c426..e8dd7e824cc9 100644 --- a/internal/sources/mssql/mssql.go +++ b/internal/sources/mssql/mssql.go @@ -28,14 +28,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "mssql" +const SourceType string = "mssql" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -50,7 +50,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { // Cloud SQL MSSQL configs Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -59,9 +59,9 @@ type Config struct { Encrypt string `yaml:"encrypt"` } -func (r Config) SourceConfigKind() string { - // Returns Cloud SQL MSSQL source kind - return SourceKind +func (r Config) SourceConfigType() string { + // Returns Cloud SQL MSSQL source type + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -91,9 +91,9 @@ type Source struct { Db *sql.DB } -func (s *Source) SourceKind() string { - // Returns Cloud SQL MSSQL source kind - return SourceKind +func (s *Source) SourceType() string { + // Returns Cloud SQL MSSQL source type + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -156,7 +156,7 @@ func initMssqlConnection( error, ) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) diff --git a/internal/sources/mssql/mssql_test.go b/internal/sources/mssql/mssql_test.go index b1fa552b46cc..26b682fafa6a 100644 --- a/internal/sources/mssql/mssql_test.go +++ b/internal/sources/mssql/mssql_test.go @@ -15,11 +15,12 @@ package mssql_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/mssql" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlMssql(t *testing.T) { { desc: "basic example", in: ` - sources: - my-mssql-instance: - kind: mssql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mssql-instance + type: mssql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mssql-instance": mssql.Config{ Name: "my-mssql-instance", - Kind: mssql.SourceKind, + Type: mssql.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -57,20 +58,20 @@ func TestParseFromYamlMssql(t *testing.T) { { desc: "with encrypt field", in: ` - sources: - my-mssql-instance: - kind: mssql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - encrypt: strict + kind: sources + name: my-mssql-instance + type: mssql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + encrypt: strict `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mssql-instance": mssql.Config{ Name: "my-mssql-instance", - Kind: mssql.SourceKind, + Type: mssql.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -83,16 +84,12 @@ func TestParseFromYamlMssql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect psarse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect psarse: want %v, got %v", tc.want, got) } }) } @@ -107,39 +104,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-mssql-instance: - kind: mssql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-mssql-instance + type: mssql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-mssql-instance\" as \"mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | kind: mssql\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-mssql-instance\" as \"mssql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-mssql-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-mssql-instance: - kind: mssql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user + kind: sources + name: my-mssql-instance + type: mssql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user `, - err: "unable to parse source \"my-mssql-instance\" as \"mssql\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-mssql-instance\" as \"mssql\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/mysql/mysql.go b/internal/sources/mysql/mysql.go index b456ec9a3f9a..626e72c817f0 100644 --- a/internal/sources/mysql/mysql.go +++ b/internal/sources/mysql/mysql.go @@ -30,14 +30,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "mysql" +const SourceType string = "mysql" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,7 +51,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { QueryParams map[string]string `yaml:"queryParams"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -90,8 +90,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -158,7 +158,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initMySQLConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, queryTimeout string, queryParams map[string]string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Build query parameters via url.Values for deterministic order and proper escaping. diff --git a/internal/sources/mysql/mysql_test.go b/internal/sources/mysql/mysql_test.go index 2cbce3bc50d5..fc6dd348c739 100644 --- a/internal/sources/mysql/mysql_test.go +++ b/internal/sources/mysql/mysql_test.go @@ -19,12 +19,12 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "go.opentelemetry.io/otel/trace/noop" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/mysql" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -38,19 +38,19 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "basic example", in: ` - sources: - my-mysql-instance: - kind: mysql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: mysql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": mysql.Config{ Name: "my-mysql-instance", - Kind: mysql.SourceKind, + Type: mysql.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -62,20 +62,20 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "with query timeout", in: ` - sources: - my-mysql-instance: - kind: mysql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - queryTimeout: 45s + kind: sources + name: my-mysql-instance + type: mysql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + queryTimeout: 45s `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": mysql.Config{ Name: "my-mysql-instance", - Kind: mysql.SourceKind, + Type: mysql.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -88,22 +88,22 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { { desc: "with query params", in: ` - sources: - my-mysql-instance: - kind: mysql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - queryParams: - tls: preferred - charset: utf8mb4 + kind: sources + name: my-mysql-instance + type: mysql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + queryParams: + tls: preferred + charset: utf8mb4 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-mysql-instance": mysql.Config{ Name: "my-mysql-instance", - Kind: mysql.SourceKind, + Type: mysql.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -120,15 +120,11 @@ func TestParseFromYamlCloudSQLMySQL(t *testing.T) { for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Sources, cmpopts.EquateEmpty()); diff != "" { + if diff := cmp.Diff(tc.want, got, cmpopts.EquateEmpty()); diff != "" { t.Fatalf("mismatch (-want +got):\n%s", diff) } }) @@ -145,55 +141,51 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-mysql-instance: - kind: mysql - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-mysql-instance + type: mysql + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unknown field \"foo\"", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"mysql\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-mysql-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-mysql-instance: - kind: mysql - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: mysql + port: my-port + database: my_db + user: my_user + password: my_pass `, - err: "Field validation for 'Host' failed", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"mysql\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, { desc: "invalid query params type", in: ` - sources: - my-mysql-instance: - kind: mysql - host: 0.0.0.0 - port: 3306 - database: my_db - user: my_user - password: my_pass - queryParams: not-a-map + kind: sources + name: my-mysql-instance + type: mysql + host: 0.0.0.0 + port: 3306 + database: my_db + user: my_user + password: my_pass + queryParams: not-a-map `, - err: "string was used where mapping is expected", + err: "error unmarshaling sources: unable to parse source \"my-mysql-instance\" as \"mysql\": [6:14] string was used where mapping is expected\n 3 | name: my-mysql-instance\n 4 | password: my_pass\n 5 | port: 3306\n> 6 | queryParams: not-a-map\n ^\n 7 | type: mysql\n 8 | user: my_user", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } @@ -211,7 +203,7 @@ func TestFailInitialization(t *testing.T) { cfg := mysql.Config{ Name: "instance", - Kind: "mysql", + Type: "mysql", Host: "localhost", Port: "3306", Database: "db", diff --git a/internal/sources/neo4j/neo4j.go b/internal/sources/neo4j/neo4j.go index 70cc21ae14e3..79af308cbf6d 100644 --- a/internal/sources/neo4j/neo4j.go +++ b/internal/sources/neo4j/neo4j.go @@ -29,7 +29,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "neo4j" +const SourceType string = "neo4j" var sourceClassifier *classifier.QueryClassifier = classifier.NewQueryClassifier() @@ -37,8 +37,8 @@ var sourceClassifier *classifier.QueryClassifier = classifier.NewQueryClassifier var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -52,15 +52,15 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Uri string `yaml:"uri" validate:"required"` User string `yaml:"user" validate:"required"` Password string `yaml:"password" validate:"required"` Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -91,8 +91,8 @@ type Source struct { Driver neo4j.DriverWithContext } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -182,7 +182,7 @@ func addPlanChildren(p neo4j.Plan) []map[string]any { func initNeo4jDriver(ctx context.Context, tracer trace.Tracer, uri, user, password, name string) (neo4j.DriverWithContext, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() auth := neo4j.BasicAuth(user, password, "") diff --git a/internal/sources/neo4j/neo4j_test.go b/internal/sources/neo4j/neo4j_test.go index 2ac8aab53468..35e3e87d5035 100644 --- a/internal/sources/neo4j/neo4j_test.go +++ b/internal/sources/neo4j/neo4j_test.go @@ -15,11 +15,12 @@ package neo4j_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/neo4j" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,18 +34,18 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "basic example", in: ` - sources: - my-neo4j-instance: - kind: neo4j - uri: neo4j+s://my-host:7687 - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-neo4j-instance + type: neo4j + uri: neo4j+s://my-host:7687 + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-neo4j-instance": neo4j.Config{ Name: "my-neo4j-instance", - Kind: neo4j.SourceKind, + Type: neo4j.SourceType, Uri: "neo4j+s://my-host:7687", Database: "my_db", User: "my_user", @@ -55,16 +56,12 @@ func TestParseFromYamlNeo4j(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -80,37 +77,33 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-neo4j-instance: - kind: neo4j - uri: neo4j+s://my-host:7687 - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-neo4j-instance + type: neo4j + uri: neo4j+s://my-host:7687 + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-neo4j-instance\" as \"neo4j\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | kind: neo4j\n 4 | password: my_pass\n 5 | uri: neo4j+s://my-host:7687\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-neo4j-instance\" as \"neo4j\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | name: my-neo4j-instance\n 4 | password: my_pass\n 5 | type: neo4j\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-neo4j-instance: - kind: neo4j - uri: neo4j+s://my-host:7687 - database: my_db - user: my_user + kind: sources + name: my-neo4j-instance + type: neo4j + uri: neo4j+s://my-host:7687 + database: my_db + user: my_user `, - err: "unable to parse source \"my-neo4j-instance\" as \"neo4j\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-neo4j-instance\" as \"neo4j\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/oceanbase/oceanbase.go b/internal/sources/oceanbase/oceanbase.go index 27a989ae3da2..0138838f6485 100644 --- a/internal/sources/oceanbase/oceanbase.go +++ b/internal/sources/oceanbase/oceanbase.go @@ -27,14 +27,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "oceanbase" +const SourceType string = "oceanbase" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -48,7 +48,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -57,8 +57,8 @@ type Config struct { QueryTimeout string `yaml:"queryTimeout"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -86,8 +86,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -153,7 +153,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an } func initOceanBaseConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, queryTimeout string) (*sql.DB, error) { - _, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + _, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, pass, host, port, dbname) diff --git a/internal/sources/oceanbase/oceanbase_test.go b/internal/sources/oceanbase/oceanbase_test.go index a21a5e065543..bfde68da95e1 100644 --- a/internal/sources/oceanbase/oceanbase_test.go +++ b/internal/sources/oceanbase/oceanbase_test.go @@ -15,11 +15,12 @@ package oceanbase_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/oceanbase" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -34,19 +35,19 @@ func TestParseFromYamlOceanBase(t *testing.T) { { desc: "basic example", in: ` - sources: - my-oceanbase-instance: - kind: oceanbase - host: 0.0.0.0 - port: 2881 - database: ob_db - user: ob_user - password: ob_pass + kind: sources + name: my-oceanbase-instance + type: oceanbase + host: 0.0.0.0 + port: 2881 + database: ob_db + user: ob_user + password: ob_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-oceanbase-instance": oceanbase.Config{ Name: "my-oceanbase-instance", - Kind: oceanbase.SourceKind, + Type: oceanbase.SourceType, Host: "0.0.0.0", Port: "2881", Database: "ob_db", @@ -58,20 +59,20 @@ func TestParseFromYamlOceanBase(t *testing.T) { { desc: "with query timeout", in: ` - sources: - my-oceanbase-instance: - kind: oceanbase - host: 0.0.0.0 - port: 2881 - database: ob_db - user: ob_user - password: ob_pass - queryTimeout: 30s + kind: sources + name: my-oceanbase-instance + type: oceanbase + host: 0.0.0.0 + port: 2881 + database: ob_db + user: ob_user + password: ob_pass + queryTimeout: 30s `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-oceanbase-instance": oceanbase.Config{ Name: "my-oceanbase-instance", - Kind: oceanbase.SourceKind, + Type: oceanbase.SourceType, Host: "0.0.0.0", Port: "2881", Database: "ob_db", @@ -84,16 +85,12 @@ func TestParseFromYamlOceanBase(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -109,39 +106,35 @@ func TestFailParseFromYamlOceanBase(t *testing.T) { { desc: "extra field", in: ` - sources: - my-oceanbase-instance: - kind: oceanbase - host: 0.0.0.0 - port: 2881 - database: ob_db - user: ob_user - password: ob_pass - foo: bar + kind: sources + name: my-oceanbase-instance + type: oceanbase + host: 0.0.0.0 + port: 2881 + database: ob_db + user: ob_user + password: ob_pass + foo: bar `, - err: "unable to parse source \"my-oceanbase-instance\" as \"oceanbase\": [2:1] unknown field \"foo\"\n 1 | database: ob_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | kind: oceanbase\n 5 | password: ob_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-oceanbase-instance\" as \"oceanbase\": [2:1] unknown field \"foo\"\n 1 | database: ob_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-oceanbase-instance\n 5 | password: ob_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-oceanbase-instance: - kind: oceanbase - port: 2881 - database: ob_db - user: ob_user - password: ob_pass + kind: sources + name: my-oceanbase-instance + type: oceanbase + port: 2881 + database: ob_db + user: ob_user + password: ob_pass `, - err: "unable to parse source \"my-oceanbase-instance\" as \"oceanbase\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-oceanbase-instance\" as \"oceanbase\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/oracle/oracle.go b/internal/sources/oracle/oracle.go index 29d78cc7061f..f9202323ce22 100644 --- a/internal/sources/oracle/oracle.go +++ b/internal/sources/oracle/oracle.go @@ -18,14 +18,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "oracle" +const SourceType string = "oracle" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -45,7 +45,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` ConnectionString string `yaml:"connectionString,omitempty"` TnsAlias string `yaml:"tnsAlias,omitempty"` TnsAdmin string `yaml:"tnsAdmin,omitempty"` @@ -95,8 +95,8 @@ func (c Config) validate() error { return nil } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -124,8 +124,8 @@ type Source struct { DB *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -239,7 +239,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initOracleConnection(ctx context.Context, tracer trace.Tracer, config Config) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, config.Name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, config.Name) defer span.End() logger, err := util.LoggerFromContext(ctx) diff --git a/internal/sources/oracle/oracle_test.go b/internal/sources/oracle/oracle_test.go index 3d8f4c7ba56f..dc9875341b0f 100644 --- a/internal/sources/oracle/oracle_test.go +++ b/internal/sources/oracle/oracle_test.go @@ -3,12 +3,13 @@ package oracle_test import ( + "context" "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/oracle" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -22,18 +23,18 @@ func TestParseFromYamlOracle(t *testing.T) { { desc: "connection string and useOCI=true", in: ` - sources: - my-oracle-cs: - kind: oracle - connectionString: "my-host:1521/XEPDB1" - user: my_user - password: my_pass - useOCI: true - `, - want: server.SourceConfigs{ + kind: sources + name: my-oracle-cs + type: oracle + connectionString: "my-host:1521/XEPDB1" + user: my_user + password: my_pass + useOCI: true + `, + want: map[string]sources.SourceConfig{ "my-oracle-cs": oracle.Config{ Name: "my-oracle-cs", - Kind: oracle.SourceKind, + Type: oracle.SourceType, ConnectionString: "my-host:1521/XEPDB1", User: "my_user", Password: "my_pass", @@ -44,19 +45,19 @@ func TestParseFromYamlOracle(t *testing.T) { { desc: "host/port/serviceName and default useOCI=false", in: ` - sources: - my-oracle-host: - kind: oracle - host: my-host - port: 1521 - serviceName: ORCLPDB - user: my_user - password: my_pass - `, - want: server.SourceConfigs{ + kind: sources + name: my-oracle-host + type: oracle + host: my-host + port: 1521 + serviceName: ORCLPDB + user: my_user + password: my_pass + `, + want: map[string]sources.SourceConfig{ "my-oracle-host": oracle.Config{ Name: "my-oracle-host", - Kind: oracle.SourceKind, + Type: oracle.SourceType, Host: "my-host", Port: 1521, ServiceName: "ORCLPDB", @@ -69,19 +70,19 @@ func TestParseFromYamlOracle(t *testing.T) { { desc: "tnsAlias and TnsAdmin specified with explicit useOCI=true", in: ` - sources: - my-oracle-tns-oci: - kind: oracle - tnsAlias: FINANCE_DB - tnsAdmin: /opt/oracle/network/admin - user: my_user - password: my_pass - useOCI: true - `, - want: server.SourceConfigs{ + kind: sources + name: my-oracle-tns-oci + type: oracle + tnsAlias: FINANCE_DB + tnsAdmin: /opt/oracle/network/admin + user: my_user + password: my_pass + useOCI: true + `, + want: map[string]sources.SourceConfig{ "my-oracle-tns-oci": oracle.Config{ Name: "my-oracle-tns-oci", - Kind: oracle.SourceKind, + Type: oracle.SourceType, TnsAlias: "FINANCE_DB", TnsAdmin: "/opt/oracle/network/admin", User: "my_user", @@ -93,22 +94,18 @@ func TestParseFromYamlOracle(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse:\nwant: %v\ngot: %v\ndiff: %s", tc.want, got.Sources, cmp.Diff(tc.want, got.Sources)) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse:\nwant: %v\ngot: %v\ndiff: %s", tc.want, got, cmp.Diff(tc.want, got)) } }) } } -func TestFailParseFromYamlOracle(t *testing.T) { +func TestFailParseFromYaml(t *testing.T) { tcs := []struct { desc string in string @@ -117,76 +114,72 @@ func TestFailParseFromYamlOracle(t *testing.T) { { desc: "extra field", in: ` - sources: - my-oracle-instance: - kind: oracle - host: my-host - serviceName: ORCL - user: my_user - password: my_pass - extraField: value + kind: sources + name: my-oracle-instance + type: oracle + host: my-host + serviceName: ORCL + user: my_user + password: my_pass + extraField: value `, - err: "unable to parse source \"my-oracle-instance\" as \"oracle\": [1:1] unknown field \"extraField\"\n> 1 | extraField: value\n ^\n 2 | host: my-host\n 3 | kind: oracle\n 4 | password: my_pass\n 5 | ", + err: "error unmarshaling sources: unable to parse source \"my-oracle-instance\" as \"oracle\": [1:1] unknown field \"extraField\"\n> 1 | extraField: value\n ^\n 2 | host: my-host\n 3 | name: my-oracle-instance\n 4 | password: my_pass\n 5 | ", }, { desc: "missing required password field", in: ` - sources: - my-oracle-instance: - kind: oracle - host: my-host - serviceName: ORCL - user: my_user - `, - err: "unable to parse source \"my-oracle-instance\" as \"oracle\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + kind: sources + name: my-oracle-instance + type: oracle + host: my-host + serviceName: ORCL + user: my_user + `, + err: "error unmarshaling sources: unable to parse source \"my-oracle-instance\" as \"oracle\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, { desc: "missing connection method fields (validate fails)", in: ` - sources: - my-oracle-instance: - kind: oracle - user: my_user - password: my_pass - `, - err: "unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: must provide one of: 'tns_alias', 'connection_string', or both 'host' and 'service_name'", + kind: sources + name: my-oracle-instance + type: oracle + user: my_user + password: my_pass + `, + err: "error unmarshaling sources: unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: must provide one of: 'tns_alias', 'connection_string', or both 'host' and 'service_name'", }, { desc: "multiple connection methods provided (validate fails)", in: ` - sources: - my-oracle-instance: - kind: oracle - host: my-host - serviceName: ORCL - connectionString: "my-host:1521/XEPDB1" - user: my_user - password: my_pass - `, - err: "unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: provide only one connection method: 'tns_alias', 'connection_string', or 'host'+'service_name'", + kind: sources + name: my-oracle-instance + type: oracle + host: my-host + serviceName: ORCL + connectionString: "my-host:1521/XEPDB1" + user: my_user + password: my_pass + `, + err: "error unmarshaling sources: unable to parse source \"my-oracle-instance\" as \"oracle\": invalid Oracle configuration: provide only one connection method: 'tns_alias', 'connection_string', or 'host'+'service_name'", }, { desc: "fail on tnsAdmin with useOCI=false", in: ` - sources: - my-oracle-fail: - kind: oracle - tnsAlias: FINANCE_DB - tnsAdmin: /opt/oracle/network/admin - user: my_user - password: my_pass - useOCI: false + kind: sources + name: my-oracle-fail + type: oracle + tnsAlias: FINANCE_DB + tnsAdmin: /opt/oracle/network/admin + user: my_user + password: my_pass + useOCI: false `, - err: "unable to parse source \"my-oracle-fail\" as \"oracle\": invalid Oracle configuration: `tnsAdmin` can only be used when `UseOCI` is true, or use `walletLocation` instead", + err: "error unmarshaling sources: unable to parse source \"my-oracle-fail\" as \"oracle\": invalid Oracle configuration: `tnsAdmin` can only be used when `UseOCI` is true, or use `walletLocation` instead", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/postgres/postgres.go b/internal/sources/postgres/postgres.go index d23721fc06fb..65d7a17b75dc 100644 --- a/internal/sources/postgres/postgres.go +++ b/internal/sources/postgres/postgres.go @@ -28,14 +28,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "postgres" +const SourceType string = "postgres" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -49,7 +49,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -58,8 +58,8 @@ type Config struct { QueryParams map[string]string `yaml:"queryParams"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -87,8 +87,8 @@ type Source struct { Pool *pgxpool.Pool } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -128,7 +128,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initPostgresConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname string, queryParams map[string]string) (*pgxpool.Pool, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() userAgent, err := util.UserAgentFromContext(ctx) if err != nil { diff --git a/internal/sources/postgres/postgres_test.go b/internal/sources/postgres/postgres_test.go index b9d8872c3a03..4bcde0420e51 100644 --- a/internal/sources/postgres/postgres_test.go +++ b/internal/sources/postgres/postgres_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,13 +15,14 @@ package postgres_test import ( + "context" "sort" "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/postgres" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -35,19 +36,19 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example", in: ` - sources: - my-pg-instance: - kind: postgres - host: my-host - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-pg-instance + type: postgres + host: my-host + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": postgres.Config{ Name: "my-pg-instance", - Kind: postgres.SourceKind, + Type: postgres.SourceType, Host: "my-host", Port: "my-port", Database: "my_db", @@ -59,22 +60,22 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "example with query params", in: ` - sources: - my-pg-instance: - kind: postgres - host: my-host - port: my-port - database: my_db - user: my_user - password: my_pass - queryParams: - sslmode: verify-full - sslrootcert: /tmp/ca.crt + kind: sources + name: my-pg-instance + type: postgres + host: my-host + port: my-port + database: my_db + user: my_user + password: my_pass + queryParams: + sslmode: verify-full + sslrootcert: /tmp/ca.crt `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-pg-instance": postgres.Config{ Name: "my-pg-instance", - Kind: postgres.SourceKind, + Type: postgres.SourceType, Host: "my-host", Port: "my-port", Database: "my_db", @@ -90,16 +91,12 @@ func TestParseFromYamlPostgres(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -115,39 +112,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-pg-instance: - kind: postgres - host: my-host - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-pg-instance + type: postgres + host: my-host + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-pg-instance\" as \"postgres\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: my-host\n 4 | kind: postgres\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"postgres\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: my-host\n 4 | name: my-pg-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-pg-instance: - kind: postgres - host: my-host - port: my-port - database: my_db - user: my_user + kind: sources + name: my-pg-instance + type: postgres + host: my-host + port: my-port + database: my_db + user: my_user `, - err: "unable to parse source \"my-pg-instance\" as \"postgres\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-pg-instance\" as \"postgres\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/redis/redis.go b/internal/sources/redis/redis.go index f8e4bfa40ed1..e2a28c52a7e3 100644 --- a/internal/sources/redis/redis.go +++ b/internal/sources/redis/redis.go @@ -24,14 +24,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "redis" +const SourceType string = "redis" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -45,7 +45,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Address []string `yaml:"address" validate:"required"` Username string `yaml:"username"` Password string `yaml:"password"` @@ -54,8 +54,8 @@ type Config struct { ClusterEnabled bool `yaml:"clusterEnabled"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } // RedisClient is an interface for `redis.Client` and `redis.ClusterClient @@ -141,8 +141,8 @@ type Source struct { Client RedisClient } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/redis/redis_test.go b/internal/sources/redis/redis_test.go index 4fe944b9247c..63e2d01beecd 100644 --- a/internal/sources/redis/redis_test.go +++ b/internal/sources/redis/redis_test.go @@ -15,12 +15,13 @@ package redis_test import ( + "context" "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/redis" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -34,16 +35,16 @@ func TestParseFromYamlRedis(t *testing.T) { { desc: "default setting", in: ` - sources: - my-redis-instance: - kind: redis - address: - - 127.0.0.1 + kind: sources + name: my-redis-instance + type: redis + address: + - 127.0.0.1 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-redis-instance": redis.Config{ Name: "my-redis-instance", - Kind: redis.SourceKind, + Type: redis.SourceType, Address: []string{"127.0.0.1"}, ClusterEnabled: false, UseGCPIAM: false, @@ -53,20 +54,20 @@ func TestParseFromYamlRedis(t *testing.T) { { desc: "advanced example", in: ` - sources: - my-redis-instance: - kind: redis - address: - - 127.0.0.1 - password: my-pass - database: 1 - useGCPIAM: true - clusterEnabled: true + kind: sources + name: my-redis-instance + type: redis + address: + - 127.0.0.1 + password: my-pass + database: 1 + useGCPIAM: true + clusterEnabled: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-redis-instance": redis.Config{ Name: "my-redis-instance", - Kind: redis.SourceKind, + Type: redis.SourceType, Address: []string{"127.0.0.1"}, Password: "my-pass", Database: 1, @@ -78,16 +79,12 @@ func TestParseFromYamlRedis(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -103,48 +100,43 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid database", in: ` - sources: - my-redis-instance: - kind: redis - project: my-project - address: - - 127.0.0.1 - password: my-pass - database: data + kind: sources + name: my-redis-instance + type: redis + address: + - 127.0.0.1 + password: my-pass + database: data `, - err: "cannot unmarshal string into Go struct field .Sources of type int", + err: "error unmarshaling sources: unable to parse source \"my-redis-instance\" as \"redis\": [3:11] cannot unmarshal string into Go struct field Config.Database of type int\n 1 | address:\n 2 | - 127.0.0.1\n> 3 | database: data\n ^\n 4 | name: my-redis-instance\n 5 | password: my-pass\n 6 | type: redis", }, { desc: "extra field", in: ` - sources: - my-redis-instance: - kind: redis - project: my-project - address: - - 127.0.0.1 - password: my-pass - database: 1 + kind: sources + name: my-redis-instance + type: redis + project: my-project + address: + - 127.0.0.1 + password: my-pass + database: 1 `, - err: "unable to parse source \"my-redis-instance\" as \"redis\": [6:1] unknown field \"project\"", + err: "error unmarshaling sources: unable to parse source \"my-redis-instance\" as \"redis\": [6:1] unknown field \"project\"\n 3 | database: 1\n 4 | name: my-redis-instance\n 5 | password: my-pass\n> 6 | project: my-project\n ^\n 7 | type: redis", }, { desc: "missing required field", in: ` - sources: - my-redis-instance: - kind: redis + kind: sources + name: my-redis-instance + type: redis `, - err: "unable to parse source \"my-redis-instance\" as \"redis\": Key: 'Config.Address' Error:Field validation for 'Address' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-redis-instance\" as \"redis\": Key: 'Config.Address' Error:Field validation for 'Address' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/serverlessspark/serverlessspark.go b/internal/sources/serverlessspark/serverlessspark.go index f6968f9baec4..a6edb82a48ef 100644 --- a/internal/sources/serverlessspark/serverlessspark.go +++ b/internal/sources/serverlessspark/serverlessspark.go @@ -33,14 +33,14 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) -const SourceKind string = "serverless-spark" +const SourceType string = "serverless-spark" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -54,13 +54,13 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Location string `yaml:"location" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -94,8 +94,8 @@ type Source struct { OpsClient *longrunning.OperationsClient } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/serverlessspark/serverlessspark_test.go b/internal/sources/serverlessspark/serverlessspark_test.go index 3162f259ef32..7e8144990541 100644 --- a/internal/sources/serverlessspark/serverlessspark_test.go +++ b/internal/sources/serverlessspark/serverlessspark_test.go @@ -15,11 +15,12 @@ package serverlessspark_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/serverlessspark" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,16 +34,16 @@ func TestParseFromYamlServerlessSpark(t *testing.T) { { desc: "basic example", in: ` - sources: - my-instance: - kind: serverless-spark - project: my-project - location: my-location + kind: sources + name: my-instance + type: serverless-spark + project: my-project + location: my-location `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-instance": serverlessspark.Config{ Name: "my-instance", - Kind: serverlessspark.SourceKind, + Type: serverlessspark.SourceType, Project: "my-project", Location: "my-location", }, @@ -51,16 +52,12 @@ func TestParseFromYamlServerlessSpark(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -76,43 +73,39 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-instance: - kind: serverless-spark - project: my-project - location: my-location - foo: bar + kind: sources + name: my-instance + type: serverless-spark + project: my-project + location: my-location + foo: bar `, - err: "unable to parse source \"my-instance\" as \"serverless-spark\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | kind: serverless-spark\n 3 | location: my-location\n 4 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"serverless-spark\": [1:1] unknown field \"foo\"\n> 1 | foo: bar\n ^\n 2 | location: my-location\n 3 | name: my-instance\n 4 | project: my-project\n 5 | ", }, { desc: "missing required field project", in: ` - sources: - my-instance: - kind: serverless-spark - location: my-location + kind: sources + name: my-instance + type: serverless-spark + location: my-location `, - err: "unable to parse source \"my-instance\" as \"serverless-spark\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"serverless-spark\": Key: 'Config.Project' Error:Field validation for 'Project' failed on the 'required' tag", }, { desc: "missing required field location", in: ` - sources: - my-instance: - kind: serverless-spark - project: my-project + kind: sources + name: my-instance + type: serverless-spark + project: my-project `, - err: "unable to parse source \"my-instance\" as \"serverless-spark\": Key: 'Config.Location' Error:Field validation for 'Location' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-instance\" as \"serverless-spark\": Key: 'Config.Location' Error:Field validation for 'Location' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/singlestore/singlestore.go b/internal/sources/singlestore/singlestore.go index ebcede392e4d..2d6f1c7807c3 100644 --- a/internal/sources/singlestore/singlestore.go +++ b/internal/sources/singlestore/singlestore.go @@ -29,15 +29,15 @@ import ( "go.opentelemetry.io/otel/trace" ) -// SourceKind for SingleStore source -const SourceKind string = "singlestore" +// SourceType for SingleStore source +const SourceType string = "singlestore" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -52,7 +52,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources // Config holds the configuration parameters for connecting to a SingleStore database. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -61,9 +61,9 @@ type Config struct { QueryTimeout string `yaml:"queryTimeout"` } -// SourceConfigKind returns the kind of the source configuration. -func (r Config) SourceConfigKind() string { - return SourceKind +// SourceConfigType returns the type of the source configuration. +func (r Config) SourceConfigType() string { + return SourceType } // Initialize sets up the SingleStore connection pool and returns a Source. @@ -93,9 +93,9 @@ type Source struct { Pool *sql.DB } -// SourceKind returns the kind of the source configuration. -func (s *Source) SourceKind() string { - return SourceKind +// SourceType returns the type of the source configuration. +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -162,7 +162,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initSingleStoreConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, queryTimeout string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the driver to connect to the database diff --git a/internal/sources/singlestore/singlestore_test.go b/internal/sources/singlestore/singlestore_test.go index 101df5300a3f..f996921db03d 100644 --- a/internal/sources/singlestore/singlestore_test.go +++ b/internal/sources/singlestore/singlestore_test.go @@ -1,5 +1,3 @@ -package singlestore_test - // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,12 +12,15 @@ package singlestore_test // See the License for the specific language governing permissions and // limitations under the License. +package singlestore_test + import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/singlestore" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - sources: - my-s2-instance: - kind: singlestore - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-s2-instance + type: singlestore + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-s2-instance": singlestore.Config{ Name: "my-s2-instance", - Kind: singlestore.SourceKind, + Type: singlestore.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -57,20 +58,20 @@ func TestParseFromYaml(t *testing.T) { { desc: "with query timeout", in: ` - sources: - my-s2-instance: - kind: singlestore - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - queryTimeout: 45s + kind: sources + name: my-s2-instance + type: singlestore + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + queryTimeout: 45s `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-s2-instance": singlestore.Config{ Name: "my-s2-instance", - Kind: singlestore.SourceKind, + Type: singlestore.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -83,16 +84,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -108,39 +105,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-s2-instance: - kind: singlestore - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - foo: bar + kind: sources + name: my-s2-instance + type: singlestore + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + foo: bar `, - err: "unable to parse source \"my-s2-instance\" as \"singlestore\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | kind: singlestore\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-s2-instance\" as \"singlestore\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-s2-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-s2-instance: - kind: singlestore - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-s2-instance + type: singlestore + port: my-port + database: my_db + user: my_user + password: my_pass `, - err: "unable to parse source \"my-s2-instance\" as \"singlestore\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-s2-instance\" as \"singlestore\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/snowflake/snowflake.go b/internal/sources/snowflake/snowflake.go index af44eb2ecef1..b08f0580b36b 100644 --- a/internal/sources/snowflake/snowflake.go +++ b/internal/sources/snowflake/snowflake.go @@ -25,14 +25,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "snowflake" +const SourceType string = "snowflake" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -46,7 +46,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Account string `yaml:"account" validate:"required"` User string `yaml:"user" validate:"required"` Password string `yaml:"password" validate:"required"` @@ -56,8 +56,8 @@ type Config struct { Role string `yaml:"role"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -85,8 +85,8 @@ type Source struct { DB *sqlx.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -137,7 +137,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initSnowflakeConnection(ctx context.Context, tracer trace.Tracer, name, account, user, password, database, schema, warehouse, role string) (*sqlx.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Set defaults for optional parameters diff --git a/internal/sources/snowflake/snowflake_test.go b/internal/sources/snowflake/snowflake_test.go index 54d7114849a0..f9437ec49ca2 100644 --- a/internal/sources/snowflake/snowflake_test.go +++ b/internal/sources/snowflake/snowflake_test.go @@ -15,11 +15,12 @@ package snowflake_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/snowflake" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlSnowflake(t *testing.T) { { desc: "basic example", in: ` - sources: - my-snowflake-instance: - kind: snowflake - account: my-account - user: my_user - password: my_pass - database: my_db - schema: my_schema + kind: sources + name: my-snowflake-instance + type: snowflake + account: my-account + user: my_user + password: my_pass + database: my_db + schema: my_schema `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-snowflake-instance": snowflake.Config{ Name: "my-snowflake-instance", - Kind: snowflake.SourceKind, + Type: snowflake.SourceType, Account: "my-account", User: "my_user", Password: "my_pass", @@ -59,16 +60,12 @@ func TestParseFromYamlSnowflake(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -84,39 +81,35 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-snowflake-instance: - kind: snowflake - account: my-account - user: my_user - password: my_pass - database: my_db - schema: my_schema - foo: bar + kind: sources + name: my-snowflake-instance + type: snowflake + account: my-account + user: my_user + password: my_pass + database: my_db + schema: my_schema + foo: bar `, - err: "unable to parse source \"my-snowflake-instance\" as \"snowflake\": [3:1] unknown field \"foo\"\n 1 | account: my-account\n 2 | database: my_db\n> 3 | foo: bar\n ^\n 4 | kind: snowflake\n 5 | password: my_pass\n 6 | schema: my_schema\n 7 | ", + err: "error unmarshaling sources: unable to parse source \"my-snowflake-instance\" as \"snowflake\": [3:1] unknown field \"foo\"\n 1 | account: my-account\n 2 | database: my_db\n> 3 | foo: bar\n ^\n 4 | name: my-snowflake-instance\n 5 | password: my_pass\n 6 | schema: my_schema\n 7 | ", }, { desc: "missing required field", in: ` - sources: - my-snowflake-instance: - kind: snowflake - account: my-account - user: my_user - password: my_pass - database: my_db + kind: sources + name: my-snowflake-instance + type: snowflake + account: my-account + user: my_user + password: my_pass + database: my_db `, - err: "unable to parse source \"my-snowflake-instance\" as \"snowflake\": Key: 'Config.Schema' Error:Field validation for 'Schema' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-snowflake-instance\" as \"snowflake\": Key: 'Config.Schema' Error:Field validation for 'Schema' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/sources.go b/internal/sources/sources.go index 10e6d57e1754..93ae0233b127 100644 --- a/internal/sources/sources.go +++ b/internal/sources/sources.go @@ -29,48 +29,48 @@ type SourceConfigFactory func(ctx context.Context, name string, decoder *yaml.De var sourceRegistry = make(map[string]SourceConfigFactory) -// Register registers a new source kind with its factory. -// It returns false if the kind is already registered. -func Register(kind string, factory SourceConfigFactory) bool { - if _, exists := sourceRegistry[kind]; exists { - // Source with this kind already exists, do not overwrite. +// Register registers a new source type with its factory. +// It returns false if the type is already registered. +func Register(sourceType string, factory SourceConfigFactory) bool { + if _, exists := sourceRegistry[sourceType]; exists { + // Source with this type already exists, do not overwrite. return false } - sourceRegistry[kind] = factory + sourceRegistry[sourceType] = factory return true } -// DecodeConfig decodes a source configuration using the registered factory for the given kind. -func DecodeConfig(ctx context.Context, kind string, name string, decoder *yaml.Decoder) (SourceConfig, error) { - factory, found := sourceRegistry[kind] +// DecodeConfig decodes a source configuration using the registered factory for the given type. +func DecodeConfig(ctx context.Context, sourceType string, name string, decoder *yaml.Decoder) (SourceConfig, error) { + factory, found := sourceRegistry[sourceType] if !found { - return nil, fmt.Errorf("unknown source kind: %q", kind) + return nil, fmt.Errorf("unknown source type: %q", sourceType) } sourceConfig, err := factory(ctx, name, decoder) if err != nil { - return nil, fmt.Errorf("unable to parse source %q as %q: %w", name, kind, err) + return nil, fmt.Errorf("unable to parse source %q as %q: %w", name, sourceType, err) } return sourceConfig, err } // SourceConfig is the interface for configuring a source. type SourceConfig interface { - SourceConfigKind() string + SourceConfigType() string Initialize(ctx context.Context, tracer trace.Tracer) (Source, error) } // Source is the interface for the source itself. type Source interface { - SourceKind() string + SourceType() string ToConfig() SourceConfig } // InitConnectionSpan adds a span for database pool connection initialization -func InitConnectionSpan(ctx context.Context, tracer trace.Tracer, sourceKind, sourceName string) (context.Context, trace.Span) { +func InitConnectionSpan(ctx context.Context, tracer trace.Tracer, sourceType, sourceName string) (context.Context, trace.Span) { ctx, span := tracer.Start( ctx, "toolbox/server/source/connect", - trace.WithAttributes(attribute.String("source_kind", sourceKind)), + trace.WithAttributes(attribute.String("source_type", sourceType)), trace.WithAttributes(attribute.String("source_name", sourceName)), ) return ctx, span diff --git a/internal/sources/spanner/spanner.go b/internal/sources/spanner/spanner.go index d6a6967e12c1..7c2f3c14649d 100644 --- a/internal/sources/spanner/spanner.go +++ b/internal/sources/spanner/spanner.go @@ -28,14 +28,14 @@ import ( "google.golang.org/api/iterator" ) -const SourceKind string = "spanner" +const SourceType string = "spanner" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -49,15 +49,15 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Project string `yaml:"project" validate:"required"` Instance string `yaml:"instance" validate:"required"` Dialect sources.Dialect `yaml:"dialect" validate:"required"` Database string `yaml:"database" validate:"required"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -80,8 +80,8 @@ type Source struct { Client *spanner.Client } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -171,7 +171,7 @@ func (s *Source) RunSQL(ctx context.Context, readOnly bool, statement string, pa func initSpannerClient(ctx context.Context, tracer trace.Tracer, name, project, instance, dbname string) (*spanner.Client, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the connection to the database diff --git a/internal/sources/spanner/spanner_test.go b/internal/sources/spanner/spanner_test.go index af0ac6a9feb8..788a3fcccd1f 100644 --- a/internal/sources/spanner/spanner_test.go +++ b/internal/sources/spanner/spanner_test.go @@ -15,9 +15,9 @@ package spanner_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,17 +34,17 @@ func TestParseFromYamlSpannerDb(t *testing.T) { { desc: "basic example", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance - database: my_db + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance + database: my_db `, want: map[string]sources.SourceConfig{ "my-spanner-instance": spanner.Config{ Name: "my-spanner-instance", - Kind: spanner.SourceKind, + Type: spanner.SourceType, Project: "my-project", Instance: "my-instance", Dialect: "googlesql", @@ -55,18 +55,18 @@ func TestParseFromYamlSpannerDb(t *testing.T) { { desc: "gsql dialect", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance - dialect: Googlesql - database: my_db + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance + dialect: Googlesql + database: my_db `, want: map[string]sources.SourceConfig{ "my-spanner-instance": spanner.Config{ Name: "my-spanner-instance", - Kind: spanner.SourceKind, + Type: spanner.SourceType, Project: "my-project", Instance: "my-instance", Dialect: "googlesql", @@ -77,18 +77,18 @@ func TestParseFromYamlSpannerDb(t *testing.T) { { desc: "postgresql dialect", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance - dialect: postgresql - database: my_db + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance + dialect: postgresql + database: my_db `, want: map[string]sources.SourceConfig{ "my-spanner-instance": spanner.Config{ Name: "my-spanner-instance", - Kind: spanner.SourceKind, + Type: spanner.SourceType, Project: "my-project", Instance: "my-instance", Dialect: "postgresql", @@ -99,16 +99,12 @@ func TestParseFromYamlSpannerDb(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -124,48 +120,44 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid dialect", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance - dialect: fail - database: my_db + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance + dialect: fail + database: my_db `, - err: "unable to parse source \"my-spanner-instance\" as \"spanner\": dialect invalid: must be one of \"googlesql\", or \"postgresql\"", + err: "error unmarshaling sources: unable to parse source \"my-spanner-instance\" as \"spanner\": dialect invalid: must be one of \"googlesql\", or \"postgresql\"", }, { desc: "extra field", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance - database: my_db - foo: bar + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance + database: my_db + foo: bar `, - err: "unable to parse source \"my-spanner-instance\" as \"spanner\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | kind: spanner\n 5 | project: my-project", + err: "error unmarshaling sources: unable to parse source \"my-spanner-instance\" as \"spanner\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | instance: my-instance\n 4 | name: my-spanner-instance\n 5 | project: my-project\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-spanner-instance: - kind: spanner - project: my-project - instance: my-instance + kind: sources + name: my-spanner-instance + type: spanner + project: my-project + instance: my-instance `, - err: "unable to parse source \"my-spanner-instance\" as \"spanner\": Key: 'Config.Database' Error:Field validation for 'Database' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-spanner-instance\" as \"spanner\": Key: 'Config.Database' Error:Field validation for 'Database' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/sqlite/sqlite.go b/internal/sources/sqlite/sqlite.go index f2afc57f9cb1..c90b932deabb 100644 --- a/internal/sources/sqlite/sqlite.go +++ b/internal/sources/sqlite/sqlite.go @@ -27,14 +27,14 @@ import ( _ "modernc.org/sqlite" // Pure Go SQLite driver ) -const SourceKind string = "sqlite" +const SourceType string = "sqlite" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -48,12 +48,12 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Database string `yaml:"database" validate:"required"` // Path to SQLite database file } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -81,8 +81,8 @@ type Source struct { Db *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -155,7 +155,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initSQLiteConnection(ctx context.Context, tracer trace.Tracer, name, dbPath string) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Open database connection diff --git a/internal/sources/sqlite/sqlite_test.go b/internal/sources/sqlite/sqlite_test.go index 03676790636e..7ccf10a0f1df 100644 --- a/internal/sources/sqlite/sqlite_test.go +++ b/internal/sources/sqlite/sqlite_test.go @@ -15,9 +15,9 @@ package sqlite_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -34,15 +34,15 @@ func TestParseFromYamlSQLite(t *testing.T) { { desc: "basic example", in: ` - sources: - my-sqlite-db: - kind: sqlite - database: /path/to/database.db + kind: sources + name: my-sqlite-db + type: sqlite + database: /path/to/database.db `, want: map[string]sources.SourceConfig{ "my-sqlite-db": sqlite.Config{ Name: "my-sqlite-db", - Kind: sqlite.SourceKind, + Type: sqlite.SourceType, Database: "/path/to/database.db", }, }, @@ -50,16 +50,53 @@ func TestParseFromYamlSQLite(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) + } + }) + } +} + +func TestFailParseFromYaml(t *testing.T) { + tcs := []struct { + desc string + in string + err string + }{ + { + desc: "extra field", + in: ` + kind: sources + name: my-sqlite-db + type: sqlite + database: /path/to/database.db + foo: bar + `, + err: "error unmarshaling sources: unable to parse source \"my-sqlite-db\" as \"sqlite\": [2:1] unknown field \"foo\"\n 1 | database: /path/to/database.db\n> 2 | foo: bar\n ^\n 3 | name: my-sqlite-db\n 4 | type: sqlite", + }, + { + desc: "missing required field", + in: ` + kind: sources + name: my-sqlite-db + type: sqlite + `, + err: "error unmarshaling sources: unable to parse source \"my-sqlite-db\" as \"sqlite\": Key: 'Config.Database' Error:Field validation for 'Database' failed on the 'required' tag", + }, + } + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) + if err == nil { + t.Fatalf("expect parsing to fail") + } + errStr := err.Error() + if errStr != tc.err { + t.Fatalf("unexpected error: got %q, want %q", errStr, tc.err) } }) } diff --git a/internal/sources/tidb/tidb.go b/internal/sources/tidb/tidb.go index 617da6969d3a..006e999e935a 100644 --- a/internal/sources/tidb/tidb.go +++ b/internal/sources/tidb/tidb.go @@ -27,15 +27,15 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "tidb" +const SourceType string = "tidb" const TiDBCloudHostPattern string = `gateway\d{2}\.(.+)\.(prod|dev|staging)\.(.+)\.tidbcloud\.com` // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -55,7 +55,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -64,8 +64,8 @@ type Config struct { UseSSL bool `yaml:"ssl"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -93,8 +93,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -189,7 +189,7 @@ func IsTiDBCloudHost(host string) bool { func initTiDBConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname string, useSSL bool) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Configure the driver to connect to the database diff --git a/internal/sources/tidb/tidb_test.go b/internal/sources/tidb/tidb_test.go index f9b8b8ffd1f5..9b18f52b06ec 100644 --- a/internal/sources/tidb/tidb_test.go +++ b/internal/sources/tidb/tidb_test.go @@ -15,11 +15,12 @@ package tidb_test import ( + "context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/tidb" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -33,19 +34,19 @@ func TestParseFromYamlTiDB(t *testing.T) { { desc: "basic example", in: ` - sources: - my-tidb-instance: - kind: tidb - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-tidb-instance + type: tidb + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-tidb-instance": tidb.Config{ Name: "my-tidb-instance", - Kind: tidb.SourceKind, + Type: tidb.SourceType, Host: "0.0.0.0", Port: "my-port", Database: "my_db", @@ -58,20 +59,20 @@ func TestParseFromYamlTiDB(t *testing.T) { { desc: "with SSL enabled", in: ` - sources: - my-tidb-cloud: - kind: tidb - host: gateway01.us-west-2.prod.aws.tidbcloud.com - port: 4000 - database: test_db - user: cloud_user - password: cloud_pass - ssl: true + kind: sources + name: my-tidb-cloud + type: tidb + host: gateway01.us-west-2.prod.aws.tidbcloud.com + port: 4000 + database: test_db + user: cloud_user + password: cloud_pass + ssl: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-tidb-cloud": tidb.Config{ Name: "my-tidb-cloud", - Kind: tidb.SourceKind, + Type: tidb.SourceType, Host: "gateway01.us-west-2.prod.aws.tidbcloud.com", Port: "4000", Database: "test_db", @@ -84,19 +85,19 @@ func TestParseFromYamlTiDB(t *testing.T) { { desc: "Change SSL enabled due to TiDB Cloud host", in: ` - sources: - my-tidb-cloud: - kind: tidb - host: gateway01.us-west-2.prod.aws.tidbcloud.com - port: 4000 - database: test_db - user: cloud_user - password: cloud_pass + kind: sources + name: my-tidb-cloud + type: tidb + host: gateway01.us-west-2.prod.aws.tidbcloud.com + port: 4000 + database: test_db + user: cloud_user + password: cloud_pass `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-tidb-cloud": tidb.Config{ Name: "my-tidb-cloud", - Kind: tidb.SourceKind, + Type: tidb.SourceType, Host: "gateway01.us-west-2.prod.aws.tidbcloud.com", Port: "4000", Database: "test_db", @@ -109,16 +110,12 @@ func TestParseFromYamlTiDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -134,41 +131,37 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "extra field", in: ` - sources: - my-tidb-instance: - kind: tidb - host: 0.0.0.0 - port: my-port - database: my_db - user: my_user - password: my_pass - ssl: false - foo: bar + kind: sources + name: my-tidb-instance + type: tidb + host: 0.0.0.0 + port: my-port + database: my_db + user: my_user + password: my_pass + ssl: false + foo: bar `, - err: "unable to parse source \"my-tidb-instance\" as \"tidb\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | kind: tidb\n 5 | password: my_pass\n 6 | ", + err: "error unmarshaling sources: unable to parse source \"my-tidb-instance\" as \"tidb\": [2:1] unknown field \"foo\"\n 1 | database: my_db\n> 2 | foo: bar\n ^\n 3 | host: 0.0.0.0\n 4 | name: my-tidb-instance\n 5 | password: my_pass\n 6 | ", }, { desc: "missing required field", in: ` - sources: - my-tidb-instance: - kind: tidb - port: my-port - database: my_db - user: my_user - password: my_pass - ssl: false + kind: sources + name: my-tidb-instance + type: tidb + port: my-port + database: my_db + user: my_user + password: my_pass + ssl: false `, - err: "unable to parse source \"my-tidb-instance\" as \"tidb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-tidb-instance\" as \"tidb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/trino/trino.go b/internal/sources/trino/trino.go index ed99dc3c19e5..6d468a27e888 100644 --- a/internal/sources/trino/trino.go +++ b/internal/sources/trino/trino.go @@ -30,14 +30,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "trino" +const SourceType string = "trino" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -51,7 +51,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user"` @@ -67,8 +67,8 @@ type Config struct { DisableSslVerification bool `yaml:"disableSslVerification"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -96,8 +96,8 @@ type Source struct { Pool *sql.DB } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -160,7 +160,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initTrinoConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, password, catalog, schema, queryTimeout, accessToken string, kerberosEnabled, sslEnabled bool, sslCertPath, sslCert string, disableSslVerification bool) (*sql.DB, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // Build Trino DSN diff --git a/internal/sources/trino/trino_test.go b/internal/sources/trino/trino_test.go index f59679c86b6c..236ad68fe2e7 100644 --- a/internal/sources/trino/trino_test.go +++ b/internal/sources/trino/trino_test.go @@ -15,11 +15,12 @@ package trino import ( + "context" "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -153,19 +154,19 @@ func TestParseFromYamlTrino(t *testing.T) { { desc: "basic example", in: ` - sources: - my-trino-instance: - kind: trino - host: localhost - port: "8080" - user: testuser - catalog: hive - schema: default + kind: sources + name: my-trino-instance + type: trino + host: localhost + port: "8080" + user: testuser + catalog: hive + schema: default `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-trino-instance": Config{ Name: "my-trino-instance", - Kind: SourceKind, + Type: SourceType, Host: "localhost", Port: "8080", User: "testuser", @@ -177,24 +178,24 @@ func TestParseFromYamlTrino(t *testing.T) { { desc: "example with optional fields", in: ` - sources: - my-trino-instance: - kind: trino - host: localhost - port: "8443" - user: testuser - password: testpass - catalog: hive - schema: default - queryTimeout: "30m" - accessToken: "jwt-token-here" - kerberosEnabled: true - sslEnabled: true + kind: sources + name: my-trino-instance + type: trino + host: localhost + port: "8443" + user: testuser + password: testpass + catalog: hive + schema: default + queryTimeout: "30m" + accessToken: "jwt-token-here" + kerberosEnabled: true + sslEnabled: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-trino-instance": Config{ Name: "my-trino-instance", - Kind: SourceKind, + Type: SourceType, Host: "localhost", Port: "8443", User: "testuser", @@ -211,18 +212,18 @@ func TestParseFromYamlTrino(t *testing.T) { { desc: "anonymous access without user", in: ` - sources: - my-trino-anonymous: - kind: trino - host: localhost - port: "8080" - catalog: hive - schema: default + kind: sources + name: my-trino-anonymous + type: trino + host: localhost + port: "8080" + catalog: hive + schema: default `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-trino-anonymous": Config{ Name: "my-trino-anonymous", - Kind: SourceKind, + Type: SourceType, Host: "localhost", Port: "8080", Catalog: "hive", @@ -233,26 +234,26 @@ func TestParseFromYamlTrino(t *testing.T) { { desc: "example with SSL cert path and cert", in: ` - sources: - my-trino-ssl-cert: - kind: trino - host: localhost - port: "8443" - user: testuser - catalog: hive - schema: default - sslEnabled: true - sslCertPath: /path/to/cert.pem - sslCert: |- + kind: sources + name: my-trino-ssl-cert + type: trino + host: localhost + port: "8443" + user: testuser + catalog: hive + schema: default + sslEnabled: true + sslCertPath: /path/to/cert.pem + sslCert: |- -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- - disableSslVerification: true + disableSslVerification: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-trino-ssl-cert": Config{ Name: "my-trino-ssl-cert", - Kind: SourceKind, + Type: SourceType, Host: "localhost", Port: "8443", User: "testuser", @@ -268,16 +269,12 @@ func TestParseFromYamlTrino(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } diff --git a/internal/sources/valkey/valkey.go b/internal/sources/valkey/valkey.go index 58ed2356d31e..fe56c3f5d229 100644 --- a/internal/sources/valkey/valkey.go +++ b/internal/sources/valkey/valkey.go @@ -24,14 +24,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "valkey" +const SourceType string = "valkey" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -45,7 +45,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Address []string `yaml:"address" validate:"required"` Username string `yaml:"username"` Password string `yaml:"password"` @@ -54,8 +54,8 @@ type Config struct { DisableCache bool `yaml:"disableCache"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -114,8 +114,8 @@ type Source struct { Client valkey.Client } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { diff --git a/internal/sources/valkey/valkey_test.go b/internal/sources/valkey/valkey_test.go index 58a0cc0017af..7e9ba2f396ac 100644 --- a/internal/sources/valkey/valkey_test.go +++ b/internal/sources/valkey/valkey_test.go @@ -15,10 +15,10 @@ package valkey_test import ( + "context" "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -35,16 +35,16 @@ func TestParseFromYamlValkey(t *testing.T) { { desc: "default setting", in: ` - sources: - my-valkey-instance: - kind: valkey - address: - - 127.0.0.1 + kind: sources + name: my-valkey-instance + type: valkey + address: + - 127.0.0.1 `, want: map[string]sources.SourceConfig{ "my-valkey-instance": valkey.Config{ Name: "my-valkey-instance", - Kind: valkey.SourceKind, + Type: valkey.SourceType, Address: []string{"127.0.0.1"}, Username: "", Password: "", @@ -57,21 +57,21 @@ func TestParseFromYamlValkey(t *testing.T) { { desc: "advanced example", in: ` - sources: - my-valkey-instance: - kind: valkey - address: - - 127.0.0.1 - database: 1 - username: user - password: pass - useGCPIAM: true - disableCache: true + kind: sources + name: my-valkey-instance + type: valkey + address: + - 127.0.0.1 + database: 1 + username: user + password: pass + useGCPIAM: true + disableCache: true `, want: map[string]sources.SourceConfig{ "my-valkey-instance": valkey.Config{ Name: "my-valkey-instance", - Kind: valkey.SourceKind, + Type: valkey.SourceType, Address: []string{"127.0.0.1"}, Username: "user", Password: "pass", @@ -84,16 +84,12 @@ func TestParseFromYamlValkey(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Sources) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -109,47 +105,42 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "invalid database", in: ` - sources: - my-valkey-instance: - kind: valkey - project: my-project - address: - - 127.0.0.1 - database: my-db - useGCPIAM: false + kind: sources + name: my-valkey-instance + type: valkey + address: + - 127.0.0.1 + database: my-db + useGCPIAM: false `, - err: "cannot unmarshal string into Go struct field .Sources of type int", + err: "error unmarshaling sources: unable to parse source \"my-valkey-instance\" as \"valkey\": [3:11] cannot unmarshal string into Go struct field Config.Database of type int\n 1 | address:\n 2 | - 127.0.0.1\n> 3 | database: my-db\n ^\n 4 | name: my-valkey-instance\n 5 | type: valkey\n 6 | useGCPIAM: false", }, { desc: "extra field", in: ` - sources: - my-valkey-instance: - kind: valkey - address: - - 127.0.0.1 - project: proj - database: 1 + kind: sources + name: my-valkey-instance + type: valkey + address: + - 127.0.0.1 + project: proj + database: 1 `, - err: "unable to parse source \"my-valkey-instance\" as \"valkey\": [5:1] unknown field \"project\"", + err: "error unmarshaling sources: unable to parse source \"my-valkey-instance\" as \"valkey\": [5:1] unknown field \"project\"\n 2 | - 127.0.0.1\n 3 | database: 1\n 4 | name: my-valkey-instance\n> 5 | project: proj\n ^\n 6 | type: valkey", }, { desc: "missing required field", in: ` - sources: - my-valkey-instance: - kind: valkey + kind: sources + name: my-valkey-instance + type: valkey `, - err: "unable to parse source \"my-valkey-instance\" as \"valkey\": Key: 'Config.Address' Error:Field validation for 'Address' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-valkey-instance\" as \"valkey\": Key: 'Config.Address' Error:Field validation for 'Address' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/sources/yugabytedb/yugabytedb.go b/internal/sources/yugabytedb/yugabytedb.go index 830e3ae7fe3b..8c5b1144c46d 100644 --- a/internal/sources/yugabytedb/yugabytedb.go +++ b/internal/sources/yugabytedb/yugabytedb.go @@ -24,14 +24,14 @@ import ( "go.opentelemetry.io/otel/trace" ) -const SourceKind string = "yugabytedb" +const SourceType string = "yugabytedb" // validate interface var _ sources.SourceConfig = Config{} func init() { - if !sources.Register(SourceKind, newConfig) { - panic(fmt.Sprintf("source kind %q already registered", SourceKind)) + if !sources.Register(SourceType, newConfig) { + panic(fmt.Sprintf("source type %q already registered", SourceType)) } } @@ -45,7 +45,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (sources type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Host string `yaml:"host" validate:"required"` Port string `yaml:"port" validate:"required"` User string `yaml:"user" validate:"required"` @@ -58,8 +58,8 @@ type Config struct { FailedHostReconnectDelaySeconds string `yaml:"failedHostReconnectDelaySecs"` } -func (r Config) SourceConfigKind() string { - return SourceKind +func (r Config) SourceConfigType() string { + return SourceType } func (r Config) Initialize(ctx context.Context, tracer trace.Tracer) (sources.Source, error) { @@ -87,8 +87,8 @@ type Source struct { Pool *pgxpool.Pool } -func (s *Source) SourceKind() string { - return SourceKind +func (s *Source) SourceType() string { + return SourceType } func (s *Source) ToConfig() sources.SourceConfig { @@ -130,7 +130,7 @@ func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (an func initYugabyteDBConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname, loadBalance, topologyKeys, refreshInterval, explicitFallback, failedHostTTL string) (*pgxpool.Pool, error) { //nolint:all // Reassigned ctx - ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name) + ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name) defer span.End() // urlExample := "postgres://username:password@localhost:5433/database_name" i := fmt.Sprintf("postgres://%s:%s@%s:%s/%s", user, pass, host, port, dbname) diff --git a/internal/sources/yugabytedb/yugabytedb_test.go b/internal/sources/yugabytedb/yugabytedb_test.go index 32eda8b64210..4a14e53d9343 100644 --- a/internal/sources/yugabytedb/yugabytedb_test.go +++ b/internal/sources/yugabytedb/yugabytedb_test.go @@ -15,13 +15,14 @@ package yugabytedb_test import ( + "context" "testing" "strings" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" + "github.com/googleapis/genai-toolbox/internal/sources" "github.com/googleapis/genai-toolbox/internal/sources/yugabytedb" "github.com/googleapis/genai-toolbox/internal/testutils" ) @@ -36,20 +37,19 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "only required fields", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -61,21 +61,20 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "with loadBalance only", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db - loadBalance: true + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db + loadBalance: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -88,22 +87,21 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "loadBalance with topologyKeys", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db - loadBalance: true - topologyKeys: zone1,zone2 + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db + loadBalance: true + topologyKeys: zone1,zone2 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -117,23 +115,22 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "with fallback only", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db - loadBalance: true - topologyKeys: zone1 - fallbackToTopologyKeysOnly: true + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db + loadBalance: true + topologyKeys: zone1 + fallbackToTopologyKeysOnly: true `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -148,23 +145,22 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "with refresh interval and reconnect delay", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db - loadBalance: true - ybServersRefreshInterval: 20 - failedHostReconnectDelaySecs: 5 + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db + loadBalance: true + ybServersRefreshInterval: 20 + failedHostReconnectDelaySecs: 5 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -179,25 +175,24 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { { desc: "all fields set", in: ` - sources: - my-yb-instance: - kind: yugabytedb - name: my-yb-instance - host: yb-host - port: yb-port - user: yb_user - password: yb_pass - database: yb_db - loadBalance: true - topologyKeys: zone1,zone2 - fallbackToTopologyKeysOnly: true - ybServersRefreshInterval: 30 - failedHostReconnectDelaySecs: 10 + kind: sources + name: my-yb-instance + type: yugabytedb + host: yb-host + port: yb-port + user: yb_user + password: yb_pass + database: yb_db + loadBalance: true + topologyKeys: zone1,zone2 + fallbackToTopologyKeysOnly: true + ybServersRefreshInterval: 30 + failedHostReconnectDelaySecs: 10 `, - want: server.SourceConfigs{ + want: map[string]sources.SourceConfig{ "my-yb-instance": yugabytedb.Config{ Name: "my-yb-instance", - Kind: "yugabytedb", + Type: "yugabytedb", Host: "yb-host", Port: "yb-port", User: "yb_user", @@ -215,16 +210,12 @@ func TestParseFromYamlYugabyteDB(t *testing.T) { for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse (-want +got):\n%s", cmp.Diff(tc.want, got.Sources)) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse (-want +got):\n%s", cmp.Diff(tc.want, got)) } }) } @@ -239,54 +230,48 @@ func TestFailParseFromYamlYugabyteDB(t *testing.T) { { desc: "extra field", in: ` - sources: - my-yb-source: - kind: yugabytedb - name: my-yb-source - host: yb-host - port: yb-port - database: yb_db - user: yb_user - password: yb_pass - foo: bar + kind: sources + name: my-yb-source + type: yugabytedb + host: yb-host + port: yb-port + database: yb_db + user: yb_user + password: yb_pass + foo: bar `, - err: "unable to parse source \"my-yb-source\" as \"yugabytedb\": [2:1] unknown field \"foo\"", + err: "error unmarshaling sources: unable to parse source \"my-yb-source\" as \"yugabytedb\": [2:1] unknown field \"foo\"\n 1 | database: yb_db\n> 2 | foo: bar\n ^\n 3 | host: yb-host\n 4 | name: my-yb-source\n 5 | password: yb_pass\n 6 | ", }, { desc: "missing required field (password)", in: ` - sources: - my-yb-source: - kind: yugabytedb - name: my-yb-source - host: yb-host - port: yb-port - database: yb_db - user: yb_user + kind: sources + name: my-yb-source + type: yugabytedb + host: yb-host + port: yb-port + database: yb_db + user: yb_user `, - err: "unable to parse source \"my-yb-source\" as \"yugabytedb\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-yb-source\" as \"yugabytedb\": Key: 'Config.Password' Error:Field validation for 'Password' failed on the 'required' tag", }, { desc: "missing required field (host)", in: ` - sources: - my-yb-source: - kind: yugabytedb - name: my-yb-source - port: yb-port - database: yb_db - user: yb_user - password: yb_pass + kind: sources + name: my-yb-source + type: yugabytedb + port: yb-port + database: yb_db + user: yb_user + password: yb_pass `, - err: "unable to parse source \"my-yb-source\" as \"yugabytedb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", + err: "error unmarshaling sources: unable to parse source \"my-yb-source\" as \"yugabytedb\": Key: 'Config.Host' Error:Field validation for 'Host' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expected parsing to fail") } diff --git a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go index 5996fc69a3d9..f11e13bc0d71 100644 --- a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go +++ b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-create-cluster" +const resourceType string = "alloydb-create-cluster" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the create-cluster tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -123,7 +123,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -187,7 +187,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -198,3 +198,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster_test.go b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster_test.go index b97dc8487e31..2daed2e62572 100644 --- a/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster_test.go +++ b/internal/tools/alloydb/alloydbcreatecluster/alloydbcreatecluster_test.go @@ -17,7 +17,6 @@ package alloydbcreatecluster_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-my-cluster: - kind: alloydb-create-cluster - source: my-alloydb-admin-source - description: some description + kind: tools + name: create-my-cluster + type: alloydb-create-cluster + source: my-alloydb-admin-source + description: some description `, want: server.ToolConfigs{ "create-my-cluster": alloydbcreatecluster.Config{ Name: "create-my-cluster", - Kind: "alloydb-create-cluster", + Type: "alloydb-create-cluster", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - create-my-cluster-auth: - kind: alloydb-create-cluster - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: create-my-cluster-auth + type: alloydb-create-cluster + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "create-my-cluster-auth": alloydbcreatecluster.Config{ Name: "create-my-cluster-auth", - Kind: "alloydb-create-cluster", + Type: "alloydb-create-cluster", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go index 058567fea56b..aa0723d190a3 100644 --- a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go +++ b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-create-instance" +const resourceType string = "alloydb-create-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the create-instance tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -124,7 +124,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -193,7 +193,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -204,3 +204,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance_test.go b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance_test.go index 499a23c0517c..820492d8253d 100644 --- a/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance_test.go +++ b/internal/tools/alloydb/alloydbcreateinstance/alloydbcreateinstance_test.go @@ -17,7 +17,6 @@ package alloydbcreateinstance_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-my-instance: - kind: alloydb-create-instance - source: my-alloydb-admin-source - description: some description + kind: tools + name: create-my-instance + type: alloydb-create-instance + source: my-alloydb-admin-source + description: some description `, want: server.ToolConfigs{ "create-my-instance": alloydbcreateinstance.Config{ Name: "create-my-instance", - Kind: "alloydb-create-instance", + Type: "alloydb-create-instance", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - create-my-instance-auth: - kind: alloydb-create-instance - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: create-my-instance-auth + type: alloydb-create-instance + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "create-my-instance-auth": alloydbcreateinstance.Config{ Name: "create-my-instance-auth", - Kind: "alloydb-create-instance", + Type: "alloydb-create-instance", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go index a5cb25855495..fc5ebdf83f6d 100644 --- a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go +++ b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-create-user" +const resourceType string = "alloydb-create-user" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the create-user tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -123,7 +123,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -198,7 +198,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -209,3 +209,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser_test.go b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser_test.go index 1a35b3093e0d..234a9d35b88e 100644 --- a/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser_test.go +++ b/internal/tools/alloydb/alloydbcreateuser/alloydbcreateuser_test.go @@ -17,7 +17,6 @@ package alloydbcreateuser_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-my-user: - kind: alloydb-create-user - source: my-alloydb-admin-source - description: some description + kind: tools + name: create-my-user + type: alloydb-create-user + source: my-alloydb-admin-source + description: some description `, want: server.ToolConfigs{ "create-my-user": alloydbcreateuser.Config{ Name: "create-my-user", - Kind: "alloydb-create-user", + Type: "alloydb-create-user", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - create-my-user-auth: - kind: alloydb-create-user - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: create-my-user-auth + type: alloydb-create-user + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "create-my-user-auth": alloydbcreateuser.Config{ Name: "create-my-user-auth", - Kind: "alloydb-create-user", + Type: "alloydb-create-user", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go index 392edeff3e6f..a2d853962f26 100644 --- a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go +++ b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-get-cluster" +const resourceType string = "alloydb-get-cluster" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the get-cluster tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -121,7 +121,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -180,3 +180,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster_test.go b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster_test.go index d30a335cd011..7ae2d11fee16 100644 --- a/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster_test.go +++ b/internal/tools/alloydb/alloydbgetcluster/alloydbgetcluster_test.go @@ -17,7 +17,6 @@ package alloydbgetcluster_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - get-my-cluster: - kind: alloydb-get-cluster - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: get-my-cluster + type: alloydb-get-cluster + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "get-my-cluster": alloydbgetcluster.Config{ Name: "get-my-cluster", - Kind: "alloydb-get-cluster", + Type: "alloydb-get-cluster", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - get-my-cluster-auth: - kind: alloydb-get-cluster - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: get-my-cluster-auth + type: alloydb-get-cluster + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "get-my-cluster-auth": alloydbgetcluster.Config{ Name: "get-my-cluster-auth", - Kind: "alloydb-get-cluster", + Type: "alloydb-get-cluster", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go index eeff94721c31..d3b31f15653f 100644 --- a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go +++ b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-get-instance" +const resourceType string = "alloydb-get-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the get-instance tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -121,7 +121,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -173,7 +173,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -184,3 +184,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance_test.go b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance_test.go index 62e9339222e5..498934fdfd4c 100644 --- a/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance_test.go +++ b/internal/tools/alloydb/alloydbgetinstance/alloydbgetinstance_test.go @@ -17,7 +17,6 @@ package alloydbgetinstance_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - get-my-instance: - kind: alloydb-get-instance - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: get-my-instance + type: alloydb-get-instance + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "get-my-instance": alloydbgetinstance.Config{ Name: "get-my-instance", - Kind: "alloydb-get-instance", + Type: "alloydb-get-instance", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - get-my-instance-auth: - kind: alloydb-get-instance - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: get-my-instance-auth + type: alloydb-get-instance + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "get-my-instance-auth": alloydbgetinstance.Config{ Name: "get-my-instance-auth", - Kind: "alloydb-get-instance", + Type: "alloydb-get-instance", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go index 31d2222f62a6..debc1bc54ef6 100644 --- a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go +++ b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-get-user" +const resourceType string = "alloydb-get-user" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the get-user tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -121,7 +121,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -173,7 +173,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -184,3 +184,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser_test.go b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser_test.go index 0d20ea325998..f601dc30d2d8 100644 --- a/internal/tools/alloydb/alloydbgetuser/alloydbgetuser_test.go +++ b/internal/tools/alloydb/alloydbgetuser/alloydbgetuser_test.go @@ -17,7 +17,6 @@ package alloydbgetuser_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - get-my-user: - kind: alloydb-get-user - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: get-my-user + type: alloydb-get-user + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "get-my-user": alloydbgetuser.Config{ Name: "get-my-user", - Kind: "alloydb-get-user", + Type: "alloydb-get-user", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - get-my-user-auth: - kind: alloydb-get-user - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: get-my-user-auth + type: alloydb-get-user + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "get-my-user-auth": alloydbgetuser.Config{ Name: "get-my-user-auth", - Kind: "alloydb-get-user", + Type: "alloydb-get-user", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go index 2e06cb062a3f..e689cb44c5e8 100644 --- a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go +++ b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-list-clusters" +const resourceType string = "alloydb-list-clusters" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the list-clusters tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -119,7 +119,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -163,7 +163,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -174,3 +174,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters_test.go b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters_test.go index b60a11db20df..17429df5dec1 100644 --- a/internal/tools/alloydb/alloydblistclusters/alloydblistclusters_test.go +++ b/internal/tools/alloydb/alloydblistclusters/alloydblistclusters_test.go @@ -17,7 +17,6 @@ package alloydblistclusters_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - list-my-clusters: - kind: alloydb-list-clusters - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: list-my-clusters + type: alloydb-list-clusters + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "list-my-clusters": alloydblistclusters.Config{ Name: "list-my-clusters", - Kind: "alloydb-list-clusters", + Type: "alloydb-list-clusters", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - list-my-clusters-auth: - kind: alloydb-list-clusters - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: list-my-clusters-auth + type: alloydb-list-clusters + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "list-my-clusters-auth": alloydblistclusters.Config{ Name: "list-my-clusters-auth", - Kind: "alloydb-list-clusters", + Type: "alloydb-list-clusters", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go index b7d4e05b35cc..223179bf7217 100644 --- a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go +++ b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-list-instances" +const resourceType string = "alloydb-list-instances" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the list-instances tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -120,7 +120,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -179,3 +179,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances_test.go b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances_test.go index aa667d956339..c1f95b964a74 100644 --- a/internal/tools/alloydb/alloydblistinstances/alloydblistinstances_test.go +++ b/internal/tools/alloydb/alloydblistinstances/alloydblistinstances_test.go @@ -17,7 +17,6 @@ package alloydblistinstances_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - list-my-instances: - kind: alloydb-list-instances - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: list-my-instances + type: alloydb-list-instances + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "list-my-instances": alloydblistinstances.Config{ Name: "list-my-instances", - Kind: "alloydb-list-instances", + Type: "alloydb-list-instances", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - list-my-instances-auth: - kind: alloydb-list-instances - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: list-my-instances-auth + type: alloydb-list-instances + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "list-my-instances-auth": alloydblistinstances.Config{ Name: "list-my-instances-auth", - Kind: "alloydb-list-instances", + Type: "alloydb-list-instances", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydblistusers/alloydblistusers.go b/internal/tools/alloydb/alloydblistusers/alloydblistusers.go index 3551a373a925..8f6e685cec37 100644 --- a/internal/tools/alloydb/alloydblistusers/alloydblistusers.go +++ b/internal/tools/alloydb/alloydblistusers/alloydblistusers.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-list-users" +const resourceType string = "alloydb-list-users" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Configuration for the list-users tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -120,7 +120,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -179,3 +179,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydblistusers/alloydblistusers_test.go b/internal/tools/alloydb/alloydblistusers/alloydblistusers_test.go index d2d0672684b1..6c92fcab5330 100644 --- a/internal/tools/alloydb/alloydblistusers/alloydblistusers_test.go +++ b/internal/tools/alloydb/alloydblistusers/alloydblistusers_test.go @@ -17,7 +17,6 @@ package alloydblistusers_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - list-my-users: - kind: alloydb-list-users - source: my-alloydb-admin-source - description: some description - `, + kind: tools + name: list-my-users + type: alloydb-list-users + source: my-alloydb-admin-source + description: some description + `, want: server.ToolConfigs{ "list-my-users": alloydblistusers.Config{ Name: "list-my-users", - Kind: "alloydb-list-users", + Type: "alloydb-list-users", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYaml(t *testing.T) { { desc: "with auth required", in: ` - tools: - list-my-users-auth: - kind: alloydb-list-users - source: my-alloydb-admin-source - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - `, + kind: tools + name: list-my-users-auth + type: alloydb-list-users + source: my-alloydb-admin-source + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + `, want: server.ToolConfigs{ "list-my-users-auth": alloydblistusers.Config{ Name: "list-my-users-auth", - Kind: "alloydb-list-users", + Type: "alloydb-list-users", Source: "my-alloydb-admin-source", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -78,15 +77,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go index b1996fc0ee01..3c5d6d367c09 100644 --- a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go +++ b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation.go @@ -27,7 +27,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "alloydb-wait-for-operation" +const resourceType string = "alloydb-wait-for-operation" var alloyDBConnectionMessageTemplate = `Your AlloyDB resource is ready. @@ -73,8 +73,8 @@ Please refer to the official documentation for guidance on deploying the toolbox ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -95,7 +95,7 @@ type compatibleSource interface { // Config defines the configuration for the wait-for-operation tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -110,9 +110,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -124,7 +124,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -214,7 +214,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -292,7 +292,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -303,3 +303,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation_test.go b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation_test.go index 68f92d39d603..ad9961f1b6fb 100644 --- a/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation_test.go +++ b/internal/tools/alloydb/alloydbwaitforoperation/alloydbwaitforoperation_test.go @@ -17,7 +17,6 @@ package alloydbwaitforoperation_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,20 +36,20 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - wait-for-thing: - kind: alloydb-wait-for-operation - source: some-source - description: some description - delay: 1s - maxDelay: 5s - multiplier: 1.5 - maxRetries: 5 - `, + kind: tools + name: wait-for-thing + type: alloydb-wait-for-operation + source: some-source + description: some description + delay: 1s + maxDelay: 5s + multiplier: 1.5 + maxRetries: 5 + `, want: server.ToolConfigs{ "wait-for-thing": alloydbwaitforoperation.Config{ Name: "wait-for-thing", - Kind: "alloydb-wait-for-operation", + Type: "alloydb-wait-for-operation", Source: "some-source", Description: "some description", AuthRequired: []string{}, @@ -64,15 +63,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/alloydbainl/alloydbainl.go b/internal/tools/alloydbainl/alloydbainl.go index 117abd2ad5da..6b4573e31ac5 100644 --- a/internal/tools/alloydbainl/alloydbainl.go +++ b/internal/tools/alloydbainl/alloydbainl.go @@ -27,11 +27,11 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "alloydb-ai-nl" +const resourceType string = "alloydb-ai-nl" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` NLConfig string `yaml:"nlConfig" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -128,7 +128,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -175,3 +175,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/alloydbainl/alloydbainl_test.go b/internal/tools/alloydbainl/alloydbainl_test.go index 2e618e66cc06..42dc54fa2fe3 100644 --- a/internal/tools/alloydbainl/alloydbainl_test.go +++ b/internal/tools/alloydbainl/alloydbainl_test.go @@ -17,7 +17,6 @@ package alloydbainl_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,26 +37,26 @@ func TestParseFromYamlAlloyDBNLA(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: alloydb-ai-nl - source: my-alloydb-instance - description: AlloyDB natural language query tool - nlConfig: 'my_nl_config' - authRequired: - - my-google-auth-service - nlConfigParameters: - - name: user_id - type: string - description: user_id to use - authServices: - - name: my-google-auth-service - field: sub - `, + kind: tools + name: example_tool + type: alloydb-ai-nl + source: my-alloydb-instance + description: AlloyDB natural language query tool + nlConfig: 'my_nl_config' + authRequired: + - my-google-auth-service + nlConfigParameters: + - name: user_id + type: string + description: user_id to use + authServices: + - name: my-google-auth-service + field: sub + `, want: server.ToolConfigs{ "example_tool": alloydbainl.Config{ Name: "example_tool", - Kind: "alloydb-ai-nl", + Type: "alloydb-ai-nl", Source: "my-alloydb-instance", Description: "AlloyDB natural language query tool", NLConfig: "my_nl_config", @@ -72,33 +71,33 @@ func TestParseFromYamlAlloyDBNLA(t *testing.T) { { desc: "with multiple parameters", in: ` - tools: - complex_tool: - kind: alloydb-ai-nl - source: my-alloydb-instance - description: AlloyDB natural language query tool with multiple parameters - nlConfig: 'complex_nl_config' - authRequired: - - my-google-auth-service - - other-auth-service - nlConfigParameters: - - name: user_id - type: string - description: user_id to use - authServices: - - name: my-google-auth-service - field: sub - - name: user_email - type: string - description: user_email to use - authServices: - - name: my-google-auth-service - field: user_email - `, + kind: tools + name: complex_tool + type: alloydb-ai-nl + source: my-alloydb-instance + description: AlloyDB natural language query tool with multiple parameters + nlConfig: 'complex_nl_config' + authRequired: + - my-google-auth-service + - other-auth-service + nlConfigParameters: + - name: user_id + type: string + description: user_id to use + authServices: + - name: my-google-auth-service + field: sub + - name: user_email + type: string + description: user_email to use + authServices: + - name: my-google-auth-service + field: user_email + `, want: server.ToolConfigs{ "complex_tool": alloydbainl.Config{ Name: "complex_tool", - Kind: "alloydb-ai-nl", + Type: "alloydb-ai-nl", Source: "my-alloydb-instance", Description: "AlloyDB natural language query tool with multiple parameters", NLConfig: "complex_nl_config", @@ -115,15 +114,12 @@ func TestParseFromYamlAlloyDBNLA(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution.go b/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution.go index 7f50803b0a34..73b80fc152f3 100644 --- a/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution.go +++ b/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution.go @@ -31,11 +31,11 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-analyze-contribution" +const resourceType string = "bigquery-analyze-contribution" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -68,8 +68,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -82,7 +82,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } allowedDatasets := s.BigQueryAllowedDatasets() @@ -155,7 +155,7 @@ func (t Tool) ToConfig() tools.ToolConfig { // Invoke runs the contribution analysis. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -329,7 +329,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -339,3 +339,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution_test.go b/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution_test.go index 7409acd14e9a..ceaa41035ef4 100644 --- a/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution_test.go +++ b/internal/tools/bigquery/bigqueryanalyzecontribution/bigqueryanalyzecontribution_test.go @@ -17,7 +17,6 @@ package bigqueryanalyzecontribution_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryAnalyzeContribution(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-analyze-contribution - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-analyze-contribution + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigqueryanalyzecontribution.Config{ Name: "example_tool", - Kind: "bigquery-analyze-contribution", + Type: "bigquery-analyze-contribution", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryAnalyzeContribution(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go b/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go index ff9fc8e8897a..e139c119bdba 100644 --- a/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go +++ b/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go @@ -33,7 +33,7 @@ import ( "golang.org/x/oauth2" ) -const kind string = "bigquery-conversational-analytics" +const resourceType string = "bigquery-conversational-analytics" const instructions = `**INSTRUCTIONS - FOLLOW THESE RULES:** 1. **CONTENT:** Your answer should present the supporting data and then provide a conclusion based on that data. @@ -41,8 +41,8 @@ const instructions = `**INSTRUCTIONS - FOLLOW THESE RULES:** 3. **NO CHARTS:** You are STRICTLY FORBIDDEN from generating any charts, graphs, images, or any other form of visualization.` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -107,7 +107,7 @@ type CAPayload struct { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -116,8 +116,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -130,7 +130,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } allowedDatasets := s.BigQueryAllowedDatasets() @@ -173,7 +173,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -285,7 +285,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -568,3 +568,7 @@ func appendMessage(messages []map[string]any, newMessage map[string]any) []map[s func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics_test.go b/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics_test.go index aadbbbe4b47c..153d656e5b0e 100644 --- a/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics_test.go +++ b/internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics_test.go @@ -17,7 +17,6 @@ package bigqueryconversationalanalytics_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryConversationalAnalytics(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-conversational-analytics - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-conversational-analytics + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigqueryconversationalanalytics.Config{ Name: "example_tool", - Kind: "bigquery-conversational-analytics", + Type: "bigquery-conversational-analytics", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryConversationalAnalytics(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go b/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go index 6f2fc245c9b6..2b03bf79b088 100644 --- a/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go +++ b/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go @@ -32,11 +32,11 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-execute-sql" +const resourceType string = "bigquery-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -61,7 +61,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -70,8 +70,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -84,7 +84,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } var sqlDescriptionBuilder strings.Builder @@ -153,7 +153,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -277,7 +277,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, bqClient, sql, statementType, nil, connProps) } @@ -302,7 +302,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -312,3 +312,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql_test.go b/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql_test.go index 0b5d11879c51..e341cee0ac25 100644 --- a/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql_test.go +++ b/internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql_test.go @@ -17,7 +17,6 @@ package bigqueryexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-execute-sql - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-execute-sql + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigqueryexecutesql.Config{ Name: "example_tool", - Kind: "bigquery-execute-sql", + Type: "bigquery-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigqueryforecast/bigqueryforecast.go b/internal/tools/bigquery/bigqueryforecast/bigqueryforecast.go index b3d56fb46520..c5128d324573 100644 --- a/internal/tools/bigquery/bigqueryforecast/bigqueryforecast.go +++ b/internal/tools/bigquery/bigqueryforecast/bigqueryforecast.go @@ -31,11 +31,11 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-forecast" +const resourceType string = "bigquery-forecast" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -68,8 +68,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -82,7 +82,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } allowedDatasets := s.BigQueryAllowedDatasets() @@ -134,7 +134,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -266,7 +266,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, bqClient, sql, "SELECT", nil, connProps) } @@ -292,7 +292,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -302,3 +302,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigqueryforecast/bigqueryforecast_test.go b/internal/tools/bigquery/bigqueryforecast/bigqueryforecast_test.go index 48de140b182e..0257668e36b3 100644 --- a/internal/tools/bigquery/bigqueryforecast/bigqueryforecast_test.go +++ b/internal/tools/bigquery/bigqueryforecast/bigqueryforecast_test.go @@ -17,7 +17,6 @@ package bigqueryforecast_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryForecast(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-forecast - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-forecast + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigqueryforecast.Config{ Name: "example_tool", - Kind: "bigquery-forecast", + Type: "bigquery-forecast", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryForecast(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo.go b/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo.go index 021f8f1dfb99..5a66b745eebf 100644 --- a/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo.go +++ b/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo.go @@ -28,13 +28,13 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-get-dataset-info" +const resourceType string = "bigquery-get-dataset-info" const projectKey string = "project" const datasetKey string = "dataset" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -56,7 +56,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -79,7 +79,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } defaultProjectID := s.BigQueryProject() @@ -122,7 +122,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -188,3 +188,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo_test.go b/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo_test.go index bb4fa8890fbb..5a18b9fe1f4e 100644 --- a/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo_test.go +++ b/internal/tools/bigquery/bigquerygetdatasetinfo/bigquerygetdatasetinfo_test.go @@ -17,7 +17,6 @@ package bigquerygetdatasetinfo_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryGetDatasetInfo(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-get-dataset-info - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-get-dataset-info + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerygetdatasetinfo.Config{ Name: "example_tool", - Kind: "bigquery-get-dataset-info", + Type: "bigquery-get-dataset-info", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryGetDatasetInfo(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo.go b/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo.go index b02b36689ee8..b29559206fa4 100644 --- a/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo.go +++ b/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo.go @@ -28,14 +28,14 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-get-table-info" +const resourceType string = "bigquery-get-table-info" const projectKey string = "project" const datasetKey string = "dataset" const tableKey string = "table" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -57,7 +57,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -80,7 +80,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } defaultProjectID := s.BigQueryProject() @@ -126,7 +126,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -188,7 +188,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -198,3 +198,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo_test.go b/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo_test.go index 992dc4d8433d..c196ff3a0c4f 100644 --- a/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo_test.go +++ b/internal/tools/bigquery/bigquerygettableinfo/bigquerygettableinfo_test.go @@ -17,7 +17,6 @@ package bigquerygettableinfo_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryGetTableInfo(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-get-table-info - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-get-table-info + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerygettableinfo.Config{ Name: "example_tool", - Kind: "bigquery-get-table-info", + Type: "bigquery-get-table-info", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryGetTableInfo(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids.go b/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids.go index e56fd8cf53f1..f3609978f933 100644 --- a/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids.go +++ b/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids.go @@ -28,12 +28,12 @@ import ( "google.golang.org/api/iterator" ) -const kind string = "bigquery-list-dataset-ids" +const resourceType string = "bigquery-list-dataset-ids" const projectKey string = "project" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -77,7 +77,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } var projectParameter parameters.Parameter @@ -121,7 +121,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -184,7 +184,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -194,3 +194,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids_test.go b/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids_test.go index 546410431bc8..21de3f99184f 100644 --- a/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids_test.go +++ b/internal/tools/bigquery/bigquerylistdatasetids/bigquerylistdatasetids_test.go @@ -17,7 +17,6 @@ package bigquerylistdatasetids_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryListDatasetIds(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-list-dataset-ids - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-list-dataset-ids + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerylistdatasetids.Config{ Name: "example_tool", - Kind: "bigquery-list-dataset-ids", + Type: "bigquery-list-dataset-ids", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryListDatasetIds(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids.go b/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids.go index d5489e28dd39..0c5d6eb1a8eb 100644 --- a/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids.go +++ b/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids.go @@ -29,13 +29,13 @@ import ( "google.golang.org/api/iterator" ) -const kind string = "bigquery-list-table-ids" +const resourceType string = "bigquery-list-table-ids" const projectKey string = "project" const datasetKey string = "dataset" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -57,7 +57,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -80,7 +80,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } defaultProjectID := s.BigQueryProject() @@ -125,7 +125,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -195,7 +195,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -205,3 +205,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids_test.go b/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids_test.go index 8e5076ce0fc7..7056764ccc7b 100644 --- a/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids_test.go +++ b/internal/tools/bigquery/bigquerylisttableids/bigquerylisttableids_test.go @@ -17,7 +17,6 @@ package bigquerylisttableids_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQueryListTableIds(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-list-table-ids - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-list-table-ids + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerylisttableids.Config{ Name: "example_tool", - Kind: "bigquery-list-table-ids", + Type: "bigquery-list-table-ids", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQueryListTableIds(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog.go b/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog.go index 2b2e557f887d..e93bc48aec8b 100644 --- a/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog.go +++ b/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog.go @@ -30,11 +30,11 @@ import ( "google.golang.org/api/iterator" ) -const kind string = "bigquery-search-catalog" +const resourceType string = "bigquery-search-catalog" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -187,7 +187,7 @@ func ExtractType(resourceString string) string { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -280,3 +280,7 @@ func (t Tool) McpManifest() tools.McpManifest { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog_test.go b/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog_test.go index 2885aecafb28..bb218a9cd18a 100644 --- a/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog_test.go +++ b/internal/tools/bigquery/bigquerysearchcatalog/bigquerysearchcatalog_test.go @@ -17,7 +17,6 @@ package bigquerysearchcatalog_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlBigQuerySearch(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-search-catalog - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: bigquery-search-catalog + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerysearchcatalog.Config{ Name: "example_tool", - Kind: "bigquery-search-catalog", + Type: "bigquery-search-catalog", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlBigQuerySearch(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/bigquery/bigquerysql/bigquerysql.go b/internal/tools/bigquery/bigquerysql/bigquerysql.go index b7cece9186e3..4770dff4a1cf 100644 --- a/internal/tools/bigquery/bigquerysql/bigquerysql.go +++ b/internal/tools/bigquery/bigquerysql/bigquerysql.go @@ -31,11 +31,11 @@ import ( bigqueryrestapi "google.golang.org/api/bigquery/v2" ) -const kind string = "bigquery-sql" +const resourceType string = "bigquery-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -56,7 +56,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -68,8 +68,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -105,7 +105,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -234,7 +234,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -244,3 +244,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigquery/bigquerysql/bigquerysql_test.go b/internal/tools/bigquery/bigquerysql/bigquerysql_test.go index 967fd418cde2..d646facad223 100644 --- a/internal/tools/bigquery/bigquerysql/bigquerysql_test.go +++ b/internal/tools/bigquery/bigquerysql/bigquerysql_test.go @@ -17,7 +17,6 @@ package bigquerysql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,22 +37,22 @@ func TestParseFromYamlBigQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-sql - source: my-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description - `, + kind: tools + name: example_tool + type: bigquery-sql + source: my-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + `, want: server.ToolConfigs{ "example_tool": bigquerysql.Config{ Name: "example_tool", - Kind: "bigquery-sql", + Type: "bigquery-sql", Source: "my-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -67,20 +66,16 @@ func TestParseFromYamlBigQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) } - } func TestParseFromYamlWithTemplateBigQuery(t *testing.T) { @@ -96,33 +91,33 @@ func TestParseFromYamlWithTemplateBigQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigquery-sql - source: my-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. - `, + kind: tools + name: example_tool + type: bigquery-sql + source: my-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. + `, want: server.ToolConfigs{ "example_tool": bigquerysql.Config{ Name: "example_tool", - Kind: "bigquery-sql", + Type: "bigquery-sql", Source: "my-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -140,18 +135,14 @@ func TestParseFromYamlWithTemplateBigQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) } - } diff --git a/internal/tools/bigtable/bigtable.go b/internal/tools/bigtable/bigtable.go index fbd6e5793285..653e1148af90 100644 --- a/internal/tools/bigtable/bigtable.go +++ b/internal/tools/bigtable/bigtable.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "bigtable-sql" +const resourceType string = "bigtable-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -98,7 +98,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -143,3 +143,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/bigtable/bigtable_test.go b/internal/tools/bigtable/bigtable_test.go index 6d12b341e278..7344e9fa2159 100644 --- a/internal/tools/bigtable/bigtable_test.go +++ b/internal/tools/bigtable/bigtable_test.go @@ -17,7 +17,6 @@ package bigtable_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,22 +37,22 @@ func TestParseFromYamlBigtable(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigtable-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description + kind: tools + name: example_tool + type: bigtable-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description `, want: server.ToolConfigs{ "example_tool": bigtable.Config{ Name: "example_tool", - Kind: "bigtable-sql", + Type: "bigtable-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -67,15 +66,11 @@ func TestParseFromYamlBigtable(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -96,33 +91,33 @@ func TestParseFromYamlWithTemplateBigtable(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: bigtable-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: bigtable-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": bigtable.Config{ Name: "example_tool", - Kind: "bigtable-sql", + Type: "bigtable-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -140,15 +135,11 @@ func TestParseFromYamlWithTemplateBigtable(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cassandra/cassandracql/cassandracql.go b/internal/tools/cassandra/cassandracql/cassandracql.go index 60ae4dff6d57..83fc261e80b1 100644 --- a/internal/tools/cassandra/cassandracql/cassandracql.go +++ b/internal/tools/cassandra/cassandracql/cassandracql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cassandra-cql" +const resourceType string = "cassandra-cql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -60,9 +60,9 @@ type Config struct { var _ tools.ToolConfig = Config{} -// ToolConfigKind implements tools.ToolConfig. -func (c Config) ToolConfigKind() string { - return kind +// ToolConfigType implements tools.ToolConfig. +func (c Config) ToolConfigType() string { + return resourceType } // Initialize implements tools.ToolConfig. @@ -108,7 +108,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -150,3 +150,7 @@ var _ tools.Tool = Tool{} func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cassandra/cassandracql/cassandracql_test.go b/internal/tools/cassandra/cassandracql/cassandracql_test.go index 3ed76b33f231..bcf6e128be77 100644 --- a/internal/tools/cassandra/cassandracql/cassandracql_test.go +++ b/internal/tools/cassandra/cassandracql/cassandracql_test.go @@ -17,7 +17,6 @@ package cassandracql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlCassandra(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cassandra-cql - source: my-cassandra-instance - description: some description - statement: | - SELECT * FROM CQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - `, + kind: tools + type: cassandra-cql + name: example_tool + source: my-cassandra-instance + description: some description + statement: | + SELECT * FROM CQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + `, want: server.ToolConfigs{ "example_tool": cassandracql.Config{ Name: "example_tool", - Kind: "cassandra-cql", + Type: "cassandra-cql", Source: "my-cassandra-instance", Description: "some description", Statement: "SELECT * FROM CQL_STATEMENT;\n", @@ -77,41 +76,41 @@ func TestParseFromYamlCassandra(t *testing.T) { { desc: "with template parameters", in: ` - tools: - example_tool: - kind: cassandra-cql - source: my-cassandra-instance - description: some description - statement: | - SELECT * FROM CQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: some description. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. - `, + kind: tools + type: cassandra-cql + name: example_tool + source: my-cassandra-instance + description: some description + statement: | + SELECT * FROM CQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: some description. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. + `, want: server.ToolConfigs{ "example_tool": cassandracql.Config{ Name: "example_tool", - Kind: "cassandra-cql", + Type: "cassandra-cql", Source: "my-cassandra-instance", Description: "some description", Statement: "SELECT * FROM CQL_STATEMENT;\n", @@ -131,18 +130,18 @@ func TestParseFromYamlCassandra(t *testing.T) { { desc: "without optional fields", in: ` - tools: - example_tool: - kind: cassandra-cql - source: my-cassandra-instance - description: some description - statement: | - SELECT * FROM CQL_STATEMENT; - `, + kind: tools + type: cassandra-cql + name: example_tool + source: my-cassandra-instance + description: some description + statement: | + SELECT * FROM CQL_STATEMENT; + `, want: server.ToolConfigs{ "example_tool": cassandracql.Config{ Name: "example_tool", - Kind: "cassandra-cql", + Type: "cassandra-cql", Source: "my-cassandra-instance", Description: "some description", Statement: "SELECT * FROM CQL_STATEMENT;\n", @@ -155,15 +154,12 @@ func TestParseFromYamlCassandra(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql.go b/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql.go index 191b8b3dfd57..0e1e8121e04d 100644 --- a/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql.go +++ b/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const executeSQLKind string = "clickhouse-execute-sql" +const executeSQLType string = "clickhouse-execute-sql" func init() { - if !tools.Register(executeSQLKind, newExecuteSQLConfig) { - panic(fmt.Sprintf("tool kind %q already registered", executeSQLKind)) + if !tools.Register(executeSQLType, newExecuteSQLConfig) { + panic(fmt.Sprintf("tool type %q already registered", executeSQLType)) } } @@ -47,7 +47,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -55,8 +55,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return executeSQLKind +func (cfg Config) ToolConfigType() string { + return executeSQLType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -88,7 +88,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -128,3 +128,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql_test.go b/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql_test.go index 9bc0e8716d56..47e5da5279de 100644 --- a/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql_test.go +++ b/internal/tools/clickhouse/clickhouseexecutesql/clickhouseexecutesql_test.go @@ -17,7 +17,6 @@ package clickhouse import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -36,16 +35,16 @@ func TestParseFromYamlClickHouseExecuteSQL(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: clickhouse-execute-sql - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: clickhouse-execute-sql + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "clickhouse-execute-sql", + Type: "clickhouse-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -55,14 +54,12 @@ func TestParseFromYamlClickHouseExecuteSQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + // Parse contents + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases.go b/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases.go index 7d697502ab84..c83a0875d654 100644 --- a/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases.go +++ b/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const listDatabasesKind string = "clickhouse-list-databases" +const listDatabasesType string = "clickhouse-list-databases" func init() { - if !tools.Register(listDatabasesKind, newListDatabasesConfig) { - panic(fmt.Sprintf("tool kind %q already registered", listDatabasesKind)) + if !tools.Register(listDatabasesType, newListDatabasesConfig) { + panic(fmt.Sprintf("tool type %q already registered", listDatabasesType)) } } @@ -47,7 +47,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -56,8 +56,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return listDatabasesKind +func (cfg Config) ToolConfigType() string { + return listDatabasesType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -87,7 +87,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -130,3 +130,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases_test.go b/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases_test.go index ca6d9b21b7cc..4f02cd5bfc30 100644 --- a/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases_test.go +++ b/internal/tools/clickhouse/clickhouselistdatabases/clickhouselistdatabases_test.go @@ -17,17 +17,16 @@ package clickhouse import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -func TestListDatabasesConfigToolConfigKind(t *testing.T) { +func TestListDatabasesConfigToolConfigType(t *testing.T) { cfg := Config{} - if cfg.ToolConfigKind() != listDatabasesKind { - t.Errorf("expected %q, got %q", listDatabasesKind, cfg.ToolConfigKind()) + if cfg.ToolConfigType() != listDatabasesType { + t.Errorf("expected %q, got %q", listDatabasesType, cfg.ToolConfigType()) } } @@ -44,16 +43,16 @@ func TestParseFromYamlClickHouseListDatabases(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: clickhouse-list-databases - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: clickhouse-list-databases + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "clickhouse-list-databases", + Type: "clickhouse-list-databases", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -63,14 +62,12 @@ func TestParseFromYamlClickHouseListDatabases(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + // Parse contents + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables.go b/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables.go index 7f5464c049de..89dd914973ad 100644 --- a/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables.go +++ b/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables.go @@ -25,12 +25,12 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const listTablesKind string = "clickhouse-list-tables" +const listTablesType string = "clickhouse-list-tables" const databaseKey string = "database" func init() { - if !tools.Register(listTablesKind, newListTablesConfig) { - panic(fmt.Sprintf("tool kind %q already registered", listTablesKind)) + if !tools.Register(listTablesType, newListTablesConfig) { + panic(fmt.Sprintf("tool type %q already registered", listTablesType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -57,8 +57,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return listTablesKind +func (cfg Config) ToolConfigType() string { + return listTablesType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -91,7 +91,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -152,3 +152,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables_test.go b/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables_test.go index 4500dac099ba..cfe2952f2762 100644 --- a/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables_test.go +++ b/internal/tools/clickhouse/clickhouselisttables/clickhouselisttables_test.go @@ -17,17 +17,16 @@ package clickhouse import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -func TestListTablesConfigToolConfigKind(t *testing.T) { +func TestListTablesConfigToolConfigType(t *testing.T) { cfg := Config{} - if cfg.ToolConfigKind() != listTablesKind { - t.Errorf("expected %q, got %q", listTablesKind, cfg.ToolConfigKind()) + if cfg.ToolConfigType() != listTablesType { + t.Errorf("expected %q, got %q", listTablesType, cfg.ToolConfigType()) } } @@ -44,16 +43,16 @@ func TestParseFromYamlClickHouseListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: clickhouse-list-tables - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: clickhouse-list-tables + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "clickhouse-list-tables", + Type: "clickhouse-list-tables", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -63,14 +62,12 @@ func TestParseFromYamlClickHouseListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + // Parse contents + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/clickhouse/clickhousesql/clickhousesql.go b/internal/tools/clickhouse/clickhousesql/clickhousesql.go index 5a83143e6720..ca9608acce9b 100644 --- a/internal/tools/clickhouse/clickhousesql/clickhousesql.go +++ b/internal/tools/clickhouse/clickhousesql/clickhousesql.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const sqlKind string = "clickhouse-sql" +const sqlType string = "clickhouse-sql" func init() { - if !tools.Register(sqlKind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", sqlKind)) + if !tools.Register(sqlType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", sqlType)) } } @@ -47,7 +47,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -58,8 +58,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return sqlKind +func (cfg Config) ToolConfigType() string { + return sqlType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -89,7 +89,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -135,3 +135,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/clickhouse/clickhousesql/clickhousesql_test.go b/internal/tools/clickhouse/clickhousesql/clickhousesql_test.go index 3c50305e2890..e7f38a1f6b6f 100644 --- a/internal/tools/clickhouse/clickhousesql/clickhousesql_test.go +++ b/internal/tools/clickhouse/clickhousesql/clickhousesql_test.go @@ -17,7 +17,6 @@ package clickhouse import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -27,10 +26,10 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -func TestConfigToolConfigKind(t *testing.T) { +func TestConfigToolConfigType(t *testing.T) { config := Config{} - if config.ToolConfigKind() != sqlKind { - t.Errorf("Expected %s, got %s", sqlKind, config.ToolConfigKind()) + if config.ToolConfigType() != sqlType { + t.Errorf("Expected %s, got %s", sqlType, config.ToolConfigType()) } } @@ -47,17 +46,17 @@ func TestParseFromYamlClickHouseSQL(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: clickhouse-sql - source: my-instance - description: some description - statement: SELECT 1 + kind: tools + name: example_tool + type: clickhouse-sql + source: my-instance + description: some description + statement: SELECT 1 `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "clickhouse-sql", + Type: "clickhouse-sql", Source: "my-instance", Description: "some description", Statement: "SELECT 1", @@ -68,21 +67,21 @@ func TestParseFromYamlClickHouseSQL(t *testing.T) { { desc: "with parameters", in: ` - tools: - param_tool: - kind: clickhouse-sql - source: test-source - description: Test ClickHouse tool - statement: SELECT * FROM test_table WHERE id = $1 - parameters: - - name: id - type: string - description: Test ID + kind: tools + name: param_tool + type: clickhouse-sql + source: test-source + description: Test ClickHouse tool + statement: SELECT * FROM test_table WHERE id = $1 + parameters: + - name: id + type: string + description: Test ID `, want: server.ToolConfigs{ "param_tool": Config{ Name: "param_tool", - Kind: "clickhouse-sql", + Type: "clickhouse-sql", Source: "test-source", Description: "Test ClickHouse tool", Statement: "SELECT * FROM test_table WHERE id = $1", @@ -96,14 +95,11 @@ func TestParseFromYamlClickHouseSQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -113,7 +109,7 @@ func TestParseFromYamlClickHouseSQL(t *testing.T) { func TestSQLConfigInitializeValidSource(t *testing.T) { config := Config{ Name: "test-tool", - Kind: sqlKind, + Type: sqlType, Source: "test-clickhouse", Description: "Test tool", Statement: "SELECT 1", diff --git a/internal/tools/cloudgda/cloudgda.go b/internal/tools/cloudgda/cloudgda.go index 6ea132318e3f..3c444065bd3a 100644 --- a/internal/tools/cloudgda/cloudgda.go +++ b/internal/tools/cloudgda/cloudgda.go @@ -26,7 +26,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-gemini-data-analytics-query" +const resourceType string = "cloud-gemini-data-analytics-query" // Guidance is the tool guidance string. const Guidance = `Tool guidance: @@ -44,8 +44,8 @@ Usage guidance: 2. If ` + "`natural_language_answer`" + ` is produced, use ` + "`intent_explanation`" + ` and ` + "`generated_query`" + ` to see if you need to clarify any assumptions for the user.` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -65,7 +65,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Location string `yaml:"location" validate:"required"` @@ -77,8 +77,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -121,7 +121,7 @@ func (t Tool) ToConfig() tools.ToolConfig { // Invoke executes the tool logic func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -180,7 +180,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -190,3 +190,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(_ tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudgda/cloudgda_test.go b/internal/tools/cloudgda/cloudgda_test.go index 2e92c56213be..d5e73658ea3c 100644 --- a/internal/tools/cloudgda/cloudgda_test.go +++ b/internal/tools/cloudgda/cloudgda_test.go @@ -23,7 +23,6 @@ import ( "net/http/httptest" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/server/resources" @@ -36,6 +35,10 @@ import ( ) func TestParseFromYaml(t *testing.T) { + ctx, err := testutils.ContextWithNewLogger() + if err != nil { + t.Fatalf("unexpected error: %s", err) + } t.Parallel() tcs := []struct { desc string @@ -45,30 +48,30 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - my-gda-query-tool: - kind: cloud-gemini-data-analytics-query - source: gda-api-source - description: Test Description - location: us-central1 - context: - datasourceReferences: - spannerReference: - databaseReference: - projectId: "cloud-db-nl2sql" - region: "us-central1" - instanceId: "evalbench" - databaseId: "financial" - engine: "GOOGLE_SQL" - agentContextReference: - contextSetId: "projects/cloud-db-nl2sql/locations/us-east1/contextSets/bdf_gsql_gemini_all_templates" - generationOptions: - generateQueryResult: true + kind: tools + name: my-gda-query-tool + type: cloud-gemini-data-analytics-query + source: gda-api-source + description: Test Description + location: us-central1 + context: + datasourceReferences: + spannerReference: + databaseReference: + projectId: "cloud-db-nl2sql" + region: "us-central1" + instanceId: "evalbench" + databaseId: "financial" + engine: "GOOGLE_SQL" + agentContextReference: + contextSetId: "projects/cloud-db-nl2sql/locations/us-east1/contextSets/bdf_gsql_gemini_all_templates" + generationOptions: + generateQueryResult: true `, want: map[string]tools.ToolConfig{ "my-gda-query-tool": cloudgdatool.Config{ Name: "my-gda-query-tool", - Kind: "cloud-gemini-data-analytics-query", + Type: "cloud-gemini-data-analytics-query", Source: "gda-api-source", Description: "Test Description", Location: "us-central1", @@ -100,16 +103,12 @@ func TestParseFromYaml(t *testing.T) { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Tools) { - t.Fatalf("incorrect parse: want %v, got %v", tc.want, got.Tools) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: want %v, got %v", tc.want, got) } }) } @@ -135,13 +134,13 @@ func (rt *authRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) } type mockSource struct { - kind string + Type string client *http.Client // Can be used to inject a specific client baseURL string // BaseURL is needed to implement sources.Source.BaseURL config cloudgdasrc.Config // to return from ToConfig } -func (m *mockSource) SourceKind() string { return m.kind } +func (m *mockSource) SourceType() string { return m.Type } func (m *mockSource) ToConfig() sources.SourceConfig { return m.config } func (m *mockSource) GetClient(ctx context.Context, token string) (*http.Client, error) { if m.client != nil { @@ -166,7 +165,7 @@ func TestInitialize(t *testing.T) { srcs := map[string]sources.Source{ "gda-api-source": &cloudgdasrc.Source{ - Config: cloudgdasrc.Config{Name: "gda-api-source", Kind: cloudgdasrc.SourceKind, ProjectID: "test-project"}, + Config: cloudgdasrc.Config{Name: "gda-api-source", Type: cloudgdasrc.SourceType, ProjectID: "test-project"}, Client: &http.Client{}, BaseURL: cloudgdasrc.Endpoint, }, @@ -180,7 +179,7 @@ func TestInitialize(t *testing.T) { desc: "successful initialization", cfg: cloudgdatool.Config{ Name: "my-gda-query-tool", - Kind: "cloud-gemini-data-analytics-query", + Type: "cloud-gemini-data-analytics-query", Source: "gda-api-source", Description: "Test Description", Location: "us-central1", @@ -189,7 +188,7 @@ func TestInitialize(t *testing.T) { } // Add an incompatible source for testing - srcs["incompatible-source"] = &mockSource{kind: "another-kind"} + srcs["incompatible-source"] = &mockSource{Type: "another-type"} for _, tc := range tcs { tc := tc @@ -287,7 +286,7 @@ func TestInvoke(t *testing.T) { // Create a real cloudgdasrc.Source but inject the authenticated client mockGdaSource := &cloudgdasrc.Source{ - Config: cloudgdasrc.Config{Name: "mock-gda-source", Kind: cloudgdasrc.SourceKind, ProjectID: "test-project"}, + Config: cloudgdasrc.Config{Name: "mock-gda-source", Type: cloudgdasrc.SourceType, ProjectID: "test-project"}, Client: authClient, BaseURL: mockServer.URL, } @@ -298,7 +297,7 @@ func TestInvoke(t *testing.T) { // Initialize the tool config with context toolCfg := cloudgdatool.Config{ Name: "query-data-tool", - Kind: "cloud-gemini-data-analytics-query", + Type: "cloud-gemini-data-analytics-query", Source: "mock-gda-source", Description: "Query Gemini Data Analytics", Location: "us-central1", // Set location for the test diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage.go index bd77a069f007..6b807c83225f 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage.go @@ -25,14 +25,14 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-healthcare-fhir-fetch-page" +const resourceType string = "cloud-healthcare-fhir-fetch-page" const ( pageURLKey = "pageURL" ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -134,7 +134,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -144,3 +144,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage_test.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage_test.go index de85dd867450..1b5d6816bc7f 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirfetchpage/cloudhealthcarefhirfetchpage_test.go @@ -17,7 +17,6 @@ package fhirfetchpage_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareFHIRFetchPage(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-fhir-fetch-page - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-fhir-fetch-page + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": fhirfetchpage.Config{ Name: "example_tool", - Kind: "cloud-healthcare-fhir-fetch-page", + Type: "cloud-healthcare-fhir-fetch-page", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareFHIRFetchPage(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything.go index 1e7f648d6b11..44fbe9553829 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything.go @@ -28,7 +28,7 @@ import ( "google.golang.org/api/googleapi" ) -const kind string = "cloud-healthcare-fhir-patient-everything" +const resourceType string = "cloud-healthcare-fhir-patient-everything" const ( patientIDKey = "patientID" typeFilterKey = "resourceTypesFilter" @@ -36,8 +36,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -57,7 +57,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -80,7 +80,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } idParameter := parameters.NewStringParameter(patientIDKey, "The ID of the patient FHIR resource for which the information is required") @@ -117,7 +117,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -186,7 +186,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -196,3 +196,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything_test.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything_test.go index 703fd0c2d3a8..d6caf089ff47 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatienteverything/cloudhealthcarefhirpatienteverything_test.go @@ -17,7 +17,6 @@ package fhirpatienteverything_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareFHIRPatientEverything(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-fhir-patient-everything - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-fhir-patient-everything + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": fhirpatienteverything.Config{ Name: "example_tool", - Kind: "cloud-healthcare-fhir-patient-everything", + Type: "cloud-healthcare-fhir-patient-everything", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareFHIRPatientEverything(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch.go index 8c8c0c95d36f..0638a00536e6 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch.go @@ -28,7 +28,7 @@ import ( "google.golang.org/api/googleapi" ) -const kind string = "cloud-healthcare-fhir-patient-search" +const resourceType string = "cloud-healthcare-fhir-patient-search" const ( activeKey = "active" cityKey = "city" @@ -52,8 +52,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -73,7 +73,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -82,8 +82,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -96,7 +96,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{ @@ -151,7 +151,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -259,7 +259,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -269,3 +269,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch_test.go b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch_test.go index 072fbc02d4c6..1d59af3b2301 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarefhirpatientsearch/cloudhealthcarefhirpatientsearch_test.go @@ -17,7 +17,6 @@ package fhirpatientsearch_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareFHIRPatientSearch(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-fhir-patient-search - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-fhir-patient-search + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": fhirpatientsearch.Config{ Name: "example_tool", - Kind: "cloud-healthcare-fhir-patient-search", + Type: "cloud-healthcare-fhir-patient-search", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareFHIRPatientSearch(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset.go index d26e4fd06eee..8ae0daa418d8 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset.go @@ -26,11 +26,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-get-dataset" +const resourceType string = "cloud-healthcare-get-dataset" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -91,7 +91,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -136,3 +136,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset_test.go index 3e56f2e9e4ff..e36b6b5d2dcc 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdataset/cloudhealthcaregetdataset_test.go @@ -17,7 +17,6 @@ package gethealthcaredataset_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlGetHealthcareDataset(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-dataset - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-dataset + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getdataset.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-dataset", + Type: "cloud-healthcare-get-dataset", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlGetHealthcareDataset(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore.go index 6a9b5bf75ec7..529ee8b00c2a 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore.go @@ -27,11 +27,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-get-dicom-store" +const resourceType string = "cloud-healthcare-get-dicom-store" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{} @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore_test.go index af87f20b9bbb..37ba8923e2ae 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstore/cloudhealthcaregetdicomstore_test.go @@ -17,7 +17,6 @@ package getdicomstore_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareGetDICOMStore(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-dicom-store - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-dicom-store + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getdicomstore.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-dicom-store", + Type: "cloud-healthcare-get-dicom-store", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareGetDICOMStore(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics.go index c5ade268c96f..0e5a4aaf9d56 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics.go @@ -27,11 +27,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-get-dicom-store-metrics" +const resourceType string = "cloud-healthcare-get-dicom-store-metrics" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{} @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics_test.go index 43523f7b85d9..f421a42a739d 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetdicomstoremetrics/cloudhealthcaregetdicomstoremetrics_test.go @@ -17,7 +17,6 @@ package getdicomstoremetrics_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareGetDICOMStoreMetrics(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-dicom-store-metrics - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-dicom-store-metrics + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getdicomstoremetrics.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-dicom-store-metrics", + Type: "cloud-healthcare-get-dicom-store-metrics", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareGetDICOMStoreMetrics(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource.go index 0e381b280662..f51527188f0b 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource.go @@ -26,15 +26,15 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-healthcare-get-fhir-resource" +const resourceType string = "cloud-healthcare-get-fhir-resource" const ( typeKey = "resourceType" idKey = "resourceID" ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -77,7 +77,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } typeParameter := parameters.NewStringParameter(typeKey, "The FHIR resource type to retrieve (e.g., Patient, Observation).") @@ -113,7 +113,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -171,3 +171,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource_test.go index 7c2ba5277f6c..a1ec0fd5c89d 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirresource/cloudhealthcaregetfhirresource_test.go @@ -17,7 +17,6 @@ package getfhirresource_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareGetFHIRResource(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-fhir-resource - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-fhir-resource + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getfhirresource.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-fhir-resource", + Type: "cloud-healthcare-get-fhir-resource", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareGetFHIRResource(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore.go index f3755ae0bb13..e6b791c2fd3a 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore.go @@ -27,11 +27,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-get-fhir-store" +const resourceType string = "cloud-healthcare-get-fhir-store" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{} @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore_test.go index bcf3d54e5116..007b186f3b83 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstore/cloudhealthcaregetfhirstore_test.go @@ -17,7 +17,6 @@ package getfhirstore_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareGetFHIRStore(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-fhir-store - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-fhir-store + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getfhirstore.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-fhir-store", + Type: "cloud-healthcare-get-fhir-store", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareGetFHIRStore(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics.go index f105bbd7ecab..379ec2c55330 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics.go @@ -27,11 +27,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-get-fhir-store-metrics" +const resourceType string = "cloud-healthcare-get-fhir-store-metrics" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{} @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics_test.go b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics_test.go index bd112bb00d63..36964ab7d9cb 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaregetfhirstoremetrics/cloudhealthcaregetfhirstoremetrics_test.go @@ -17,7 +17,6 @@ package getfhirstoremetrics_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareGetFHIRStoreMetrics(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-get-fhir-store-metrics - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-get-fhir-store-metrics + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": getfhirstoremetrics.Config{ Name: "example_tool", - Kind: "cloud-healthcare-get-fhir-store-metrics", + Type: "cloud-healthcare-get-fhir-store-metrics", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareGetFHIRStoreMetrics(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores.go b/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores.go index bdc4002c3af4..7c58c4bb1bff 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores.go @@ -26,11 +26,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-list-dicom-stores" +const resourceType string = "cloud-healthcare-list-dicom-stores" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -91,7 +91,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -136,3 +136,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores_test.go b/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores_test.go index f9e874b2d9d9..6967f346f1a0 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarelistdicomstores/cloudhealthcarelistdicomstores_test.go @@ -17,7 +17,6 @@ package listdicomstores_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareListDICOMStores(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-list-dicom-stores - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-list-dicom-stores + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": listdicomstores.Config{ Name: "example_tool", - Kind: "cloud-healthcare-list-dicom-stores", + Type: "cloud-healthcare-list-dicom-stores", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareListDICOMStores(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores.go b/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores.go index c7918329cd57..8bea1273d936 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores.go @@ -26,11 +26,11 @@ import ( "google.golang.org/api/healthcare/v1" ) -const kind string = "cloud-healthcare-list-fhir-stores" +const resourceType string = "cloud-healthcare-list-fhir-stores" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -91,7 +91,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -136,3 +136,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores_test.go b/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores_test.go index dc7d8d891e55..70414613ea8b 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcarelistfhirstores/cloudhealthcarelistfhirstores_test.go @@ -17,7 +17,6 @@ package listfhirstores_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareListFHIRStores(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-list-fhir-stores - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-list-fhir-stores + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": listfhirstores.Config{ Name: "example_tool", - Kind: "cloud-healthcare-list-fhir-stores", + Type: "cloud-healthcare-list-fhir-stores", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareListFHIRStores(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance.go b/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance.go index 44c7e8a612d1..f2cc29a02ae4 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance.go +++ b/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance.go @@ -26,7 +26,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-healthcare-retrieve-rendered-dicom-instance" +const resourceType string = "cloud-healthcare-retrieve-rendered-dicom-instance" const ( studyInstanceUIDKey = "StudyInstanceUID" seriesInstanceUIDKey = "SeriesInstanceUID" @@ -35,8 +35,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -56,7 +56,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -79,7 +79,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{ @@ -118,7 +118,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -174,7 +174,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -184,3 +184,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance_test.go b/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance_test.go index 1522c3d8c3b0..adf60055296f 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcareretrieverendereddicominstance/cloudhealthcareretrieverendereddicominstance_test.go @@ -17,7 +17,6 @@ package retrieverendereddicominstance_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareRetrieveRenderedDICOMInstance(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-retrieve-rendered-dicom-instance - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-retrieve-rendered-dicom-instance + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": retrieverendereddicominstance.Config{ Name: "example_tool", - Kind: "cloud-healthcare-retrieve-rendered-dicom-instance", + Type: "cloud-healthcare-retrieve-rendered-dicom-instance", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareRetrieveRenderedDICOMInstance(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances.go index 1223d09649d4..b359c74046c2 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances.go @@ -28,7 +28,7 @@ import ( "google.golang.org/api/googleapi" ) -const kind string = "cloud-healthcare-search-dicom-instances" +const resourceType string = "cloud-healthcare-search-dicom-instances" const ( studyInstanceUIDKey = "StudyInstanceUID" patientNameKey = "PatientName" @@ -42,8 +42,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -63,7 +63,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -72,8 +72,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -86,7 +86,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{ @@ -132,7 +132,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -176,7 +176,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para } } } - return source.SearchDICOM(t.Kind, storeID, dicomWebPath, tokenStr, opts) + return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts) } func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (parameters.ParamValues, error) { @@ -200,7 +200,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -210,3 +210,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances_test.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances_test.go index e28c6c1dd27e..83a3ff5de343 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicominstances/cloudhealthcaresearchdicominstances_test.go @@ -17,7 +17,6 @@ package searchdicominstances_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareSearchDICOMInstances(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-search-dicom-instances - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-search-dicom-instances + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": searchdicominstances.Config{ Name: "example_tool", - Kind: "cloud-healthcare-search-dicom-instances", + Type: "cloud-healthcare-search-dicom-instances", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareSearchDICOMInstances(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries.go index 3c72fd99c34d..35f37cb5a12b 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries.go @@ -27,7 +27,7 @@ import ( "google.golang.org/api/googleapi" ) -const kind string = "cloud-healthcare-search-dicom-series" +const resourceType string = "cloud-healthcare-search-dicom-series" const ( studyInstanceUIDKey = "StudyInstanceUID" patientNameKey = "PatientName" @@ -40,8 +40,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -61,7 +61,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -70,8 +70,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -84,7 +84,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{ @@ -129,7 +129,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para dicomWebPath = fmt.Sprintf("studies/%s/series", id) } } - return source.SearchDICOM(t.Kind, storeID, dicomWebPath, tokenStr, opts) + return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts) } func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (parameters.ParamValues, error) { @@ -185,7 +185,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -195,3 +195,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries_test.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries_test.go index 7558adcadf85..e46eb0cb0fae 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomseries/cloudhealthcaresearchdicomseries_test.go @@ -17,7 +17,6 @@ package searchdicomseries_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareSearchDICOMSeries(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-search-dicom-series - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-search-dicom-series + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": searchdicomseries.Config{ Name: "example_tool", - Kind: "cloud-healthcare-search-dicom-series", + Type: "cloud-healthcare-search-dicom-series", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareSearchDICOMSeries(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies.go index d6d92f9dbb30..e2b02248d85f 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies.go @@ -27,7 +27,7 @@ import ( "google.golang.org/api/googleapi" ) -const kind string = "cloud-healthcare-search-dicom-studies" +const resourceType string = "cloud-healthcare-search-dicom-studies" const ( studyInstanceUIDKey = "StudyInstanceUID" patientNameKey = "PatientName" @@ -38,8 +38,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -68,8 +68,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -82,7 +82,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } params := parameters.Parameters{ @@ -125,7 +125,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -145,7 +145,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para return nil, err } dicomWebPath := "studies" - return source.SearchDICOM(t.Kind, storeID, dicomWebPath, tokenStr, opts) + return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts) } func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (parameters.ParamValues, error) { @@ -169,7 +169,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -179,3 +179,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies_test.go b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies_test.go index 483f37e61b8f..6415eaedd26c 100644 --- a/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies_test.go +++ b/internal/tools/cloudhealthcare/cloudhealthcaresearchdicomstudies/cloudhealthcaresearchdicomstudies_test.go @@ -17,7 +17,6 @@ package searchdicomstudies_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlHealthcareSearchDICOMStudies(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-healthcare-search-dicom-studies - source: my-instance - description: some description + kind: tools + name: example_tool + type: cloud-healthcare-search-dicom-studies + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": searchdicomstudies.Config{ Name: "example_tool", - Kind: "cloud-healthcare-search-dicom-studies", + Type: "cloud-healthcare-search-dicom-studies", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYamlHealthcareSearchDICOMStudies(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudmonitoring/cloudmonitoring.go b/internal/tools/cloudmonitoring/cloudmonitoring.go index aab95defbeb2..0d2e9b6cec0c 100644 --- a/internal/tools/cloudmonitoring/cloudmonitoring.go +++ b/internal/tools/cloudmonitoring/cloudmonitoring.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-monitoring-query-prometheus" +const resourceType string = "cloud-monitoring-query-prometheus" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -138,3 +138,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudmonitoring/cloudmonitoring_test.go b/internal/tools/cloudmonitoring/cloudmonitoring_test.go index 51c4d00c212f..30b143444ebb 100644 --- a/internal/tools/cloudmonitoring/cloudmonitoring_test.go +++ b/internal/tools/cloudmonitoring/cloudmonitoring_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" @@ -29,12 +28,12 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -// mockIncompatibleSource is a source of a different kind to test error paths. +// mockIncompatibleSource is a source of a different type to test error paths. type mockIncompatibleSource struct{ sources.Source } func TestInitialize(t *testing.T) { t.Parallel() - testSource := &cloudmonitoringsrc.Source{Config: cloudmonitoringsrc.Config{Kind: "cloud-monitoring"}} + testSource := &cloudmonitoringsrc.Source{Config: cloudmonitoringsrc.Config{Type: "cloud-monitoring"}} srcs := map[string]sources.Source{ "my-monitoring-source": testSource, "incompatible-source": &mockIncompatibleSource{}, @@ -55,7 +54,7 @@ func TestInitialize(t *testing.T) { desc: "Success case with nil authRequired", cfg: cloudmonitoring.Config{ Name: "test-tool", - Kind: "cloud-monitoring-query-prometheus", + Type: "cloud-monitoring-query-prometheus", Source: "my-monitoring-source", Description: "A test description.", AuthRequired: nil, @@ -70,7 +69,7 @@ func TestInitialize(t *testing.T) { desc: "Success case with specified authRequired", cfg: cloudmonitoring.Config{ Name: "test-tool-with-auth", - Kind: "cloud-monitoring-query-prometheus", + Type: "cloud-monitoring-query-prometheus", Source: "my-monitoring-source", Description: "Another test description.", AuthRequired: []string{"google-auth-service"}, @@ -122,16 +121,16 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: cloud-monitoring-query-prometheus - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: cloud-monitoring-query-prometheus + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": cloudmonitoring.Config{ Name: "example_tool", - Kind: "cloud-monitoring-query-prometheus", + Type: "cloud-monitoring-query-prometheus", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -141,19 +140,19 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { { desc: "advanced example", in: ` - tools: - example_tool: - kind: cloud-monitoring-query-prometheus - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: cloud-monitoring-query-prometheus + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": cloudmonitoring.Config{ Name: "example_tool", - Kind: "cloud-monitoring-query-prometheus", + Type: "cloud-monitoring-query-prometheus", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -163,15 +162,11 @@ func TestParseFromYamlCloudMonitoring(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools, cmp.AllowUnexported(cloudmonitoring.Config{})); diff != "" { + if diff := cmp.Diff(tc.want, got, cmp.AllowUnexported(cloudmonitoring.Config{})); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -189,44 +184,40 @@ func TestFailParseFromYamlCloudMonitoring(t *testing.T) { err string }{ { - desc: "Invalid kind", + desc: "Invalid type", in: ` - tools: - example_tool: - kind: invalid-kind - source: my-instance - description: some description + kind: tools + name: example_tool + type: invalid-type + source: my-instance + description: some description `, - err: `unknown tool kind: "invalid-kind"`, + err: `unknown tool type: "invalid-type"`, }, { desc: "missing source", in: ` - tools: - example_tool: - kind: cloud-monitoring-query-prometheus - description: some description + kind: tools + name: example_tool + type: cloud-monitoring-query-prometheus + description: some description `, err: `Key: 'Config.Source' Error:Field validation for 'Source' failed on the 'required' tag`, }, { desc: "missing description", in: ` - tools: - example_tool: - kind: cloud-monitoring-query-prometheus - source: my-instance + kind: tools + name: example_tool + type: cloud-monitoring-query-prometheus + source: my-instance `, err: `Key: 'Config.Description' Error:Field validation for 'Description' failed on the 'required' tag`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance.go b/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance.go index 887d2d8f9bd9..f11520f960b2 100644 --- a/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance.go +++ b/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance.go @@ -26,11 +26,11 @@ import ( sqladmin "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-clone-instance" +const resourceType string = "cloud-sql-clone-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { // Config defines the configuration for the clone-instance tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,9 +61,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -125,7 +125,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -176,7 +176,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -187,3 +187,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance_test.go b/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance_test.go index 42fb94406d19..2cb93c60b1b2 100644 --- a/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance_test.go +++ b/internal/tools/cloudsql/cloudsqlcloneinstance/cloudsqlcloneinstance_test.go @@ -18,7 +18,6 @@ import ( //"context" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - clone-instance-tool: - kind: cloud-sql-clone-instance - description: a test description - source: a-source + kind: tools + name: clone-instance-tool + type: cloud-sql-clone-instance + description: a test description + source: a-source `, want: server.ToolConfigs{ "clone-instance-tool": cloudsqlcloneinstance.Config{ Name: "clone-instance-tool", - Kind: "cloud-sql-clone-instance", + Type: "cloud-sql-clone-instance", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup.go b/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup.go index 2ad723f0d5ab..ab1f8d3e18b7 100644 --- a/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup.go +++ b/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup.go @@ -26,7 +26,7 @@ import ( "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-create-backup" +const resourceType string = "cloud-sql-create-backup" var _ tools.ToolConfig = Config{} @@ -40,15 +40,15 @@ type compatibleSource interface { // Config defines the configuration for the create-backup tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` } func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -60,9 +60,9 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T return actual, nil } -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -121,7 +121,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -167,7 +167,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -178,3 +178,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup_test.go b/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup_test.go index f3f46a470df0..3136729817db 100644 --- a/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup_test.go +++ b/internal/tools/cloudsql/cloudsqlcreatebackup/cloudsqlcreatebackup_test.go @@ -17,7 +17,6 @@ package cloudsqlcreatebackup_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-backup-tool: - kind: cloud-sql-create-backup - description: a test description - source: a-source + kind: tools + name: create-backup-tool + type: cloud-sql-create-backup + description: a test description + source: a-source `, want: server.ToolConfigs{ "create-backup-tool": cloudsqlcreatebackup.Config{ Name: "create-backup-tool", - Kind: "cloud-sql-create-backup", + Type: "cloud-sql-create-backup", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase.go b/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase.go index bf9471be8694..e5373a771db2 100644 --- a/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase.go +++ b/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-sql-create-database" +const resourceType string = "cloud-sql-create-database" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for the create-database tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -72,7 +72,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -118,7 +118,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -165,7 +165,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -175,3 +175,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase_test.go b/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase_test.go index 8630c916b65c..7986d058502e 100644 --- a/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase_test.go +++ b/internal/tools/cloudsql/cloudsqlcreatedatabase/cloudsqlcreatedatabase_test.go @@ -17,7 +17,6 @@ package cloudsqlcreatedatabase_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-database: - kind: cloud-sql-create-database - source: my-source - description: some description + kind: tools + name: create-database + type: cloud-sql-create-database + source: my-source + description: some description `, want: server.ToolConfigs{ "create-database": cloudsqlcreatedatabase.Config{ Name: "create-database", - Kind: "cloud-sql-create-database", + Type: "cloud-sql-create-database", Source: "my-source", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers.go b/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers.go index 701e5e215131..40690b9dbaf9 100644 --- a/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers.go +++ b/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-sql-create-users" +const resourceType string = "cloud-sql-create-users" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for the create-user tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -72,7 +72,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -120,7 +120,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -170,7 +170,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -180,3 +180,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers_test.go b/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers_test.go index 594b5215cb93..6ea0ed59c1e0 100644 --- a/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers_test.go +++ b/internal/tools/cloudsql/cloudsqlcreateusers/cloudsqlcreateusers_test.go @@ -17,7 +17,6 @@ package cloudsqlcreateusers_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-user: - kind: cloud-sql-create-users - source: my-source - description: some description + kind: tools + name: create-user + type: cloud-sql-create-users + source: my-source + description: some description `, want: server.ToolConfigs{ "create-user": cloudsqlcreateusers.Config{ Name: "create-user", - Kind: "cloud-sql-create-users", + Type: "cloud-sql-create-users", Source: "my-source", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances.go b/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances.go index 6c2b57cfc246..401c61e7577c 100644 --- a/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances.go +++ b/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-sql-get-instance" +const resourceType string = "cloud-sql-get-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for the get-instances tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -118,7 +118,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -171,3 +171,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances_test.go b/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances_test.go index 809ecfa81500..249f4e20152e 100644 --- a/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances_test.go +++ b/internal/tools/cloudsql/cloudsqlgetinstances/cloudsqlgetinstances_test.go @@ -17,7 +17,6 @@ package cloudsqlgetinstances_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - get-instances: - kind: cloud-sql-get-instance - description: "A tool to get cloud sql instances" - source: "my-gcp-source" + kind: tools + name: get-instances + type: cloud-sql-get-instance + description: "A tool to get cloud sql instances" + source: "my-gcp-source" `, want: server.ToolConfigs{ "get-instances": cloudsqlgetinstances.Config{ Name: "get-instances", - Kind: "cloud-sql-get-instance", + Type: "cloud-sql-get-instance", Description: "A tool to get cloud sql instances", Source: "my-gcp-source", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases.go b/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases.go index a18c9dcffb85..9eb8eda844b6 100644 --- a/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases.go +++ b/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-sql-list-databases" +const resourceType string = "cloud-sql-list-databases" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for the list-databases tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -72,7 +72,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -117,7 +117,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -160,7 +160,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -170,3 +170,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases_test.go b/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases_test.go index f7c1d49380d6..4717110f73de 100644 --- a/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases_test.go +++ b/internal/tools/cloudsql/cloudsqllistdatabases/cloudsqllistdatabases_test.go @@ -17,7 +17,6 @@ package cloudsqllistdatabases_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - list-my-databases: - kind: cloud-sql-list-databases - description: some description - source: some-source + kind: tools + name: list-my-databases + type: cloud-sql-list-databases + description: some description + source: some-source `, want: server.ToolConfigs{ "list-my-databases": cloudsqllistdatabases.Config{ Name: "list-my-databases", - Kind: "cloud-sql-list-databases", + Type: "cloud-sql-list-databases", Description: "some description", AuthRequired: []string{}, Source: "some-source", @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances.go b/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances.go index 21ddd0a4695c..441fbf00ea74 100644 --- a/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances.go +++ b/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "cloud-sql-list-instances" +const resourceType string = "cloud-sql-list-instances" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for the list-instance tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -72,7 +72,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -116,7 +116,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -155,7 +155,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -165,3 +165,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances_test.go b/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances_test.go index bf7eabfc0972..0ef4ce1b6ec2 100644 --- a/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances_test.go +++ b/internal/tools/cloudsql/cloudsqllistinstances/cloudsqllistinstances_test.go @@ -17,7 +17,6 @@ package cloudsqllistinstances import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -36,16 +35,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - list-my-instances: - kind: cloud-sql-list-instances - description: some description - source: some-source + kind: tools + name: list-my-instances + type: cloud-sql-list-instances + description: some description + source: some-source `, want: server.ToolConfigs{ "list-my-instances": Config{ Name: "list-my-instances", - Kind: "cloud-sql-list-instances", + Type: "cloud-sql-list-instances", Description: "some description", AuthRequired: []string{}, Source: "some-source", @@ -55,15 +54,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup.go b/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup.go index 16c05f9ed3e3..bc17692cf504 100644 --- a/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup.go +++ b/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup.go @@ -26,7 +26,7 @@ import ( "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-restore-backup" +const resourceType string = "cloud-sql-restore-backup" var _ tools.ToolConfig = Config{} @@ -40,15 +40,15 @@ type compatibleSource interface { // Config defines the configuration for the restore-backup tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` } func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -60,9 +60,9 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T return actual, nil } -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -73,7 +73,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } project := s.GetDefaultProject() @@ -121,7 +121,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -170,7 +170,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,3 +181,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup_test.go b/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup_test.go index 7ed49142ed51..27c4bd7467c7 100644 --- a/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup_test.go +++ b/internal/tools/cloudsql/cloudsqlrestorebackup/cloudsqlrestorebackup_test.go @@ -17,7 +17,6 @@ package cloudsqlrestorebackup_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - restore-backup-tool: - kind: cloud-sql-restore-backup - description: a test description - source: a-source + kind: tools + name: restore-backup-tool + type: cloud-sql-restore-backup + description: a test description + source: a-source `, want: server.ToolConfigs{ "restore-backup-tool": cloudsqlrestorebackup.Config{ Name: "restore-backup-tool", - Kind: "cloud-sql-restore-backup", + Type: "cloud-sql-restore-backup", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -56,14 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation.go b/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation.go index 4da7c7faba74..841e4d6a973a 100644 --- a/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation.go +++ b/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation.go @@ -27,7 +27,7 @@ import ( "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-wait-for-operation" +const resourceType string = "cloud-sql-wait-for-operation" var cloudSQLConnectionMessageTemplate = `Your Cloud SQL resource is ready. @@ -71,8 +71,8 @@ Please refer to the official documentation for guidance on deploying the toolbox ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -94,7 +94,7 @@ type compatibleSource interface { // Config defines the configuration for the wait-for-operation tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -110,9 +110,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -124,7 +124,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -211,7 +211,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -290,7 +290,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -300,3 +300,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation_test.go b/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation_test.go index 580ee5a4f493..994cd87bb49c 100644 --- a/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation_test.go +++ b/internal/tools/cloudsql/cloudsqlwaitforoperation/cloudsqlwaitforoperation_test.go @@ -17,7 +17,6 @@ package cloudsqlwaitforoperation_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,20 +36,20 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - wait-for-thing: - kind: cloud-sql-wait-for-operation - source: some-source - description: some description - delay: 1s - maxDelay: 5s - multiplier: 1.5 - maxRetries: 5 + kind: tools + name: wait-for-thing + type: cloud-sql-wait-for-operation + source: some-source + description: some description + delay: 1s + maxDelay: 5s + multiplier: 1.5 + maxRetries: 5 `, want: server.ToolConfigs{ "wait-for-thing": cloudsqlwaitforoperation.Config{ Name: "wait-for-thing", - Kind: "cloud-sql-wait-for-operation", + Type: "cloud-sql-wait-for-operation", Source: "some-source", Description: "some description", AuthRequired: []string{}, @@ -64,15 +63,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance.go b/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance.go index 9a762935068e..fb512316ad89 100644 --- a/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance.go +++ b/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance.go @@ -27,11 +27,11 @@ import ( "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-mssql-create-instance" +const resourceType string = "cloud-sql-mssql-create-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { // Config defines the configuration for the create-instances tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,9 +61,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -122,7 +122,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -194,7 +194,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -204,3 +204,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance_test.go b/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance_test.go index 54b381ae629d..01928e87cd10 100644 --- a/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance_test.go +++ b/internal/tools/cloudsqlmssql/cloudsqlmssqlcreateinstance/cloudsqlmssqlcreateinstance_test.go @@ -17,7 +17,6 @@ package cloudsqlmssqlcreateinstance_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-instance-tool: - kind: cloud-sql-mssql-create-instance - description: a test description - source: a-source + kind: tools + name: create-instance-tool + type: cloud-sql-mssql-create-instance + description: a test description + source: a-source `, want: server.ToolConfigs{ "create-instance-tool": cloudsqlmssqlcreateinstance.Config{ Name: "create-instance-tool", - Kind: "cloud-sql-mssql-create-instance", + Type: "cloud-sql-mssql-create-instance", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance.go b/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance.go index 247544dc15d9..722cf86b3426 100644 --- a/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance.go +++ b/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance.go @@ -27,11 +27,11 @@ import ( sqladmin "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-mysql-create-instance" +const resourceType string = "cloud-sql-mysql-create-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { // Config defines the configuration for the create-instances tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,9 +61,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -122,7 +122,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -196,7 +196,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -206,3 +206,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance_test.go b/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance_test.go index eb961412c84b..88b4ea087d03 100644 --- a/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance_test.go +++ b/internal/tools/cloudsqlmysql/cloudsqlmysqlcreateinstance/cloudsqlmysqlcreateinstance_test.go @@ -17,7 +17,6 @@ package cloudsqlmysqlcreateinstance_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-instance-tool: - kind: cloud-sql-mysql-create-instance - description: a test description - source: a-source + kind: tools + name: create-instance-tool + type: cloud-sql-mysql-create-instance + description: a test description + source: a-source `, want: server.ToolConfigs{ "create-instance-tool": cloudsqlmysqlcreateinstance.Config{ Name: "create-instance-tool", - Kind: "cloud-sql-mysql-create-instance", + Type: "cloud-sql-mysql-create-instance", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances.go b/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances.go index 8fe60179f09c..2b9fb976535c 100644 --- a/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances.go +++ b/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances.go @@ -27,11 +27,11 @@ import ( sqladmin "google.golang.org/api/sqladmin/v1" ) -const kind string = "cloud-sql-postgres-create-instance" +const resourceType string = "cloud-sql-postgres-create-instance" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { // Config defines the configuration for the create-instances tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,9 +61,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -74,7 +74,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) } s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `cloud-sql-admin`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `cloud-sql-admin`", resourceType) } project := s.GetDefaultProject() @@ -122,7 +122,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -195,7 +195,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -205,3 +205,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances_test.go b/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances_test.go index 950ba8b2dedf..12dca82574ea 100644 --- a/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances_test.go +++ b/internal/tools/cloudsqlpg/cloudsqlpgcreateinstances/cloudsqlpgcreateinstances_test.go @@ -17,7 +17,6 @@ package cloudsqlpgcreateinstances_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - create-instance-tool: - kind: cloud-sql-postgres-create-instance - description: a test description - source: a-source + kind: tools + name: create-instance-tool + type: cloud-sql-postgres-create-instance + description: a test description + source: a-source `, want: server.ToolConfigs{ "create-instance-tool": cloudsqlpgcreateinstances.Config{ Name: "create-instance-tool", - Kind: "cloud-sql-postgres-create-instance", + Type: "cloud-sql-postgres-create-instance", Description: "a test description", Source: "a-source", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck.go b/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck.go index a4fd600414c8..16c65063ce83 100644 --- a/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck.go +++ b/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck.go @@ -27,11 +27,11 @@ import ( sqladmin "google.golang.org/api/sqladmin/v1" ) -const kind string = "postgres-upgrade-precheck" +const resourceType string = "postgres-upgrade-precheck" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { // Config defines the configuration for the precheck-upgrade tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize initializes the tool from the configuration. @@ -133,7 +133,7 @@ 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) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -231,7 +231,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -241,3 +241,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck_test.go b/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck_test.go index 27a117e1ba2b..790676cd7072 100644 --- a/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck_test.go +++ b/internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck_test.go @@ -17,7 +17,6 @@ package cloudsqlpgupgradeprecheck_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,18 +36,18 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic precheck example", in: ` - tools: - precheck-upgrade-tool: - kind: postgres-upgrade-precheck - description: a precheck test description - source: some-admin-source - authRequired: - - https://www.googleapis.com/auth/cloud-platform + kind: tools + name: precheck-upgrade-tool + type: postgres-upgrade-precheck + description: a precheck test description + source: some-admin-source + authRequired: + - https://www.googleapis.com/auth/cloud-platform `, want: server.ToolConfigs{ "precheck-upgrade-tool": cloudsqlpgupgradeprecheck.Config{ Name: "precheck-upgrade-tool", - Kind: "postgres-upgrade-precheck", + Type: "postgres-upgrade-precheck", Description: "a precheck test description", Source: "some-admin-source", AuthRequired: []string{"https://www.googleapis.com/auth/cloud-platform"}, @@ -58,16 +57,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "precheck example with no auth", in: ` - tools: - precheck-upgrade-tool-no-auth: - kind: postgres-upgrade-precheck - description: a precheck test description no auth - source: other-admin-source + kind: tools + name: precheck-upgrade-tool-no-auth + type: postgres-upgrade-precheck + description: a precheck test description no auth + source: other-admin-source `, want: server.ToolConfigs{ "precheck-upgrade-tool-no-auth": cloudsqlpgupgradeprecheck.Config{ Name: "precheck-upgrade-tool-no-auth", - Kind: "postgres-upgrade-precheck", + Type: "postgres-upgrade-precheck", Description: "a precheck test description no auth", Source: "other-admin-source", AuthRequired: []string{}, @@ -77,15 +76,11 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff (-want +got):\n%s", diff) } }) diff --git a/internal/tools/couchbase/couchbase.go b/internal/tools/couchbase/couchbase.go index a43c85f506f1..35880d5ca5a7 100644 --- a/internal/tools/couchbase/couchbase.go +++ b/internal/tools/couchbase/couchbase.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "couchbase-sql" +const resourceType string = "couchbase-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -97,7 +97,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -142,3 +142,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/couchbase/couchbase_test.go b/internal/tools/couchbase/couchbase_test.go index 6f8f2bc459a9..554c871c0dee 100644 --- a/internal/tools/couchbase/couchbase_test.go +++ b/internal/tools/couchbase/couchbase_test.go @@ -20,13 +20,16 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/couchbase" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" ) -func TestParseFromYamlCouchbase(t *testing.T) { +func TestParseFromYaml(t *testing.T) { + ctx, err := testutils.ContextWithNewLogger() + if err != nil { + t.Fatalf("unexpected error: %s", err) + } tcs := []struct { desc string in string @@ -35,22 +38,22 @@ func TestParseFromYamlCouchbase(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: couchbase-sql - source: my-couchbase-instance - description: some tool description - statement: | - select * from hotel WHERE name = $hotel; - parameters: - - name: hotel - type: string - description: hotel parameter description + kind: tools + name: example_tool + type: couchbase-sql + source: my-couchbase-instance + description: some tool description + statement: | + select * from hotel WHERE name = $hotel; + parameters: + - name: hotel + type: string + description: hotel parameter description `, want: server.ToolConfigs{ "example_tool": couchbase.Config{ Name: "example_tool", - Kind: "couchbase-sql", + Type: "couchbase-sql", AuthRequired: []string{}, Source: "my-couchbase-instance", Description: "some tool description", @@ -61,64 +64,29 @@ func TestParseFromYamlCouchbase(t *testing.T) { }, }, }, - } - for _, tc := range tcs { - t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - - // Create a context with a logger - ctx, err := testutils.ContextWithNewLogger() - if err != nil { - t.Fatalf("unable to create context with logger: %s", err) - } - - // Parse contents with context - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) - if err != nil { - t.Fatalf("unable to unmarshal: %s", err) - } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { - t.Fatalf("incorrect parse: diff %v", diff) - } - }) - } -} - -func TestParseFromYamlWithTemplateMssql(t *testing.T) { - ctx, err := testutils.ContextWithNewLogger() - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - tcs := []struct { - desc string - in string - want server.ToolConfigs - }{ { - desc: "basic example", + desc: "with template", in: ` - tools: - example_tool: - kind: couchbase-sql - source: my-couchbase-instance - description: some tool description - statement: | - select * from {{.tableName}} WHERE name = $hotel; - parameters: - - name: hotel - type: string - description: hotel parameter description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. + kind: tools + name: example_tool + type: couchbase-sql + source: my-couchbase-instance + description: some tool description + statement: | + select * from {{.tableName}} WHERE name = $hotel; + parameters: + - name: hotel + type: string + description: hotel parameter description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. `, want: server.ToolConfigs{ "example_tool": couchbase.Config{ Name: "example_tool", - Kind: "couchbase-sql", + Type: "couchbase-sql", AuthRequired: []string{}, Source: "my-couchbase-instance", Description: "some tool description", @@ -135,15 +103,11 @@ func TestParseFromYamlWithTemplateMssql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal.go b/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal.go index 7ab103699157..bd8d1071f645 100644 --- a/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal.go +++ b/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "dataform-compile-local" +const resourceType string = "dataform-compile-local" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -45,15 +45,15 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` } var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -130,3 +130,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal_test.go b/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal_test.go index 40b85f0363d0..89cb950aeabc 100644 --- a/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal_test.go +++ b/internal/tools/dataform/dataformcompilelocal/dataformcompilelocal_test.go @@ -17,7 +17,6 @@ package dataformcompilelocal_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,15 +36,15 @@ func TestParseFromYamlDataformCompile(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: dataform-compile-local - description: some description + kind: tools + name: example_tool + type: dataform-compile-local + description: some description `, want: server.ToolConfigs{ "example_tool": dataformcompilelocal.Config{ Name: "example_tool", - Kind: "dataform-compile-local", + Type: "dataform-compile-local", Description: "some description", AuthRequired: []string{}, }, @@ -54,15 +53,11 @@ func TestParseFromYamlDataformCompile(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry.go b/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry.go index 3fed4ef0ccfb..1eb4d2fb380e 100644 --- a/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry.go +++ b/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "dataplex-lookup-entry" +const resourceType string = "dataplex-lookup-entry" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -158,3 +158,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry_test.go b/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry_test.go index 8c3d5942c2cf..514125d5129b 100644 --- a/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry_test.go +++ b/internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry_test.go @@ -17,7 +17,6 @@ package dataplexlookupentry_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlDataplexLookupEntry(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: dataplex-lookup-entry - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: dataplex-lookup-entry + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": dataplexlookupentry.Config{ Name: "example_tool", - Kind: "dataplex-lookup-entry", + Type: "dataplex-lookup-entry", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,34 +56,34 @@ func TestParseFromYamlDataplexLookupEntry(t *testing.T) { { desc: "advanced example", in: ` - tools: - example_tool: - kind: dataplex-lookup-entry - source: my-instance - description: some description - parameters: - - name: name - type: string - description: some name description - - name: view - type: string - description: some view description - - name: aspectTypes - type: array - description: some aspect types description - default: [] - items: - name: aspectType - type: string - description: some aspect type description - - name: entry - type: string - description: some entry description - `, + kind: tools + name: example_tool + type: dataplex-lookup-entry + source: my-instance + description: some description + parameters: + - name: name + type: string + description: some name description + - name: view + type: string + description: some view description + - name: aspectTypes + type: array + description: some aspect types description + default: [] + items: + name: aspectType + type: string + description: some aspect type description + - name: entry + type: string + description: some entry description + `, want: server.ToolConfigs{ "example_tool": dataplexlookupentry.Config{ Name: "example_tool", - Kind: "dataplex-lookup-entry", + Type: "dataplex-lookup-entry", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -100,18 +99,14 @@ func TestParseFromYamlDataplexLookupEntry(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) } - } diff --git a/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes.go b/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes.go index 214f7396e19e..9384aed578db 100644 --- a/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes.go +++ b/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "dataplex-search-aspect-types" +const resourceType string = "dataplex-search-aspect-types" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -57,8 +57,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -135,3 +135,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes_test.go b/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes_test.go index 963091b03d0a..cb081ca45ff9 100644 --- a/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes_test.go +++ b/internal/tools/dataplex/dataplexsearchaspecttypes/dataplexsearchaspecttypes_test.go @@ -17,7 +17,6 @@ package dataplexsearchaspecttypes_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlDataplexSearchAspectTypes(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: dataplex-search-aspect-types - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: dataplex-search-aspect-types + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": dataplexsearchaspecttypes.Config{ Name: "example_tool", - Kind: "dataplex-search-aspect-types", + Type: "dataplex-search-aspect-types", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,18 +55,14 @@ func TestParseFromYamlDataplexSearchAspectTypes(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) } - } diff --git a/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries.go b/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries.go index 7180848a4ba9..a84814574699 100644 --- a/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries.go +++ b/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "dataplex-search-entries" +const resourceType string = "dataplex-search-entries" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -57,8 +57,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -134,3 +134,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries_test.go b/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries_test.go index f916c82f74e0..e8b80883acfb 100644 --- a/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries_test.go +++ b/internal/tools/dataplex/dataplexsearchentries/dataplexsearchentries_test.go @@ -17,7 +17,6 @@ package dataplexsearchentries_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlDataplexSearchEntries(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: dataplex-search-entries - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: dataplex-search-entries + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": dataplexsearchentries.Config{ Name: "example_tool", - Kind: "dataplex-search-entries", + Type: "dataplex-search-entries", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,18 +55,14 @@ func TestParseFromYamlDataplexSearchEntries(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) } - } diff --git a/internal/tools/dgraph/dgraph.go b/internal/tools/dgraph/dgraph.go index 7d56baadd9d3..37296c1f9a8a 100644 --- a/internal/tools/dgraph/dgraph.go +++ b/internal/tools/dgraph/dgraph.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "dgraph-dql" +const resourceType string = "dgraph-dql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -92,7 +92,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,3 +126,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/dgraph/dgraph_test.go b/internal/tools/dgraph/dgraph_test.go index cb4f672ff303..08ea32e2e404 100644 --- a/internal/tools/dgraph/dgraph_test.go +++ b/internal/tools/dgraph/dgraph_test.go @@ -17,7 +17,6 @@ package dgraph_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,20 +36,20 @@ func TestParseFromYamlDgraph(t *testing.T) { { desc: "basic query example", in: ` - tools: - example_tool: - kind: dgraph-dql - source: my-dgraph-instance - description: some tool description - isQuery: true - timeout: 20s - statement: | - query {q(func: eq(email, "example@email.com")) {email}} + kind: tools + name: example_tool + type: dgraph-dql + source: my-dgraph-instance + description: some tool description + isQuery: true + timeout: 20s + statement: | + query {q(func: eq(email, "example@email.com")) {email}} `, want: server.ToolConfigs{ "example_tool": dgraph.Config{ Name: "example_tool", - Kind: "dgraph-dql", + Type: "dgraph-dql", Source: "my-dgraph-instance", AuthRequired: []string{}, Description: "some tool description", @@ -63,18 +62,18 @@ func TestParseFromYamlDgraph(t *testing.T) { { desc: "basic mutation example", in: ` - tools: - example_tool: - kind: dgraph-dql - source: my-dgraph-instance - description: some tool description - statement: | - mutation {set { _:a "a@email.com" . _:b "b@email.com" .}} + kind: tools + name: example_tool + type: dgraph-dql + source: my-dgraph-instance + description: some tool description + statement: | + mutation {set { _:a "a@email.com" . _:b "b@email.com" .}} `, want: server.ToolConfigs{ "example_tool": dgraph.Config{ Name: "example_tool", - Kind: "dgraph-dql", + Type: "dgraph-dql", Source: "my-dgraph-instance", Description: "some tool description", AuthRequired: []string{}, @@ -85,15 +84,11 @@ func TestParseFromYamlDgraph(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql.go b/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql.go index 0e13013635ee..d386d6174d75 100644 --- a/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql.go +++ b/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql.go @@ -28,11 +28,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "elasticsearch-esql" +const resourceType string = "elasticsearch-esql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -43,7 +43,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` @@ -55,8 +55,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (c Config) ToolConfigKind() string { - return kind +func (c Config) ToolConfigType() string { + return resourceType } func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) { @@ -90,7 +90,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -153,3 +153,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql_test.go b/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql_test.go index ec65d2842a3a..aca93acdb4b8 100644 --- a/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql_test.go +++ b/internal/tools/elasticsearch/elasticsearchesql/elasticsearchesql_test.go @@ -17,7 +17,6 @@ package elasticsearchesql import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlElasticsearchEsql(t *testing.T) { { desc: "basic search example", in: ` - tools: - example_tool: - kind: elasticsearch-esql - source: my-elasticsearch-instance - description: Elasticsearch ES|QL tool - query: | - FROM my-index - | KEEP first_name, last_name + kind: tools + name: example_tool + type: elasticsearch-esql + source: my-elasticsearch-instance + description: Elasticsearch ES|QL tool + query: | + FROM my-index + | KEEP first_name, last_name `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "elasticsearch-esql", + Type: "elasticsearch-esql", Source: "my-elasticsearch-instance", Description: "Elasticsearch ES|QL tool", AuthRequired: []string{}, @@ -60,23 +59,23 @@ func TestParseFromYamlElasticsearchEsql(t *testing.T) { { desc: "search with customizable limit parameter", in: ` - tools: - example_tool: - kind: elasticsearch-esql - source: my-elasticsearch-instance - description: Elasticsearch ES|QL tool with customizable limit - parameters: - - name: limit - type: integer - description: Limit the number of results - query: | - FROM my-index - | LIMIT ?limit + kind: tools + name: example_tool + type: elasticsearch-esql + source: my-elasticsearch-instance + description: Elasticsearch ES|QL tool with customizable limit + parameters: + - name: limit + type: integer + description: Limit the number of results + query: | + FROM my-index + | LIMIT ?limit `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "elasticsearch-esql", + Type: "elasticsearch-esql", Source: "my-elasticsearch-instance", Description: "Elasticsearch ES|QL tool with customizable limit", AuthRequired: []string{}, @@ -91,15 +90,12 @@ func TestParseFromYamlElasticsearchEsql(t *testing.T) { for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql.go b/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql.go index fa5e414f6312..e96a99d0cc96 100644 --- a/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql.go +++ b/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firebird-execute-sql" +const resourceType string = "firebird-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -91,7 +91,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -138,3 +138,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql_test.go b/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql_test.go index a2f8f0235577..b91e68eb19fa 100644 --- a/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql_test.go +++ b/internal/tools/firebird/firebirdexecutesql/firebirdexecutesql_test.go @@ -17,7 +17,6 @@ package firebirdexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: firebird-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: firebird-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": firebirdexecutesql.Config{ Name: "example_tool", - Kind: "firebird-execute-sql", + Type: "firebird-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/firebird/firebirdsql/firebirdsql.go b/internal/tools/firebird/firebirdsql/firebirdsql.go index aad9b54aa58b..1973167f9b42 100644 --- a/internal/tools/firebird/firebirdsql/firebirdsql.go +++ b/internal/tools/firebird/firebirdsql/firebirdsql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firebird-sql" +const resourceType string = "firebird-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -99,7 +99,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/firebird/firebirdsql/firebirdsql_test.go b/internal/tools/firebird/firebirdsql/firebirdsql_test.go index 553069903512..e329d237ace4 100644 --- a/internal/tools/firebird/firebirdsql/firebirdsql_test.go +++ b/internal/tools/firebird/firebirdsql/firebirdsql_test.go @@ -17,7 +17,6 @@ package firebirdsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlFirebird(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: firebird-sql - source: my-fdb-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: firebird-sql + source: my-fdb-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": firebirdsql.Config{ Name: "example_tool", - Kind: "firebird-sql", + Type: "firebird-sql", Source: "my-fdb-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlFirebird(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -106,33 +102,33 @@ func TestParseFromYamlWithTemplateParamsFirebird(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: firebird-sql - source: my-fdb-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: name - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: firebird-sql + source: my-fdb-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: name + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": firebirdsql.Config{ Name: "example_tool", - Kind: "firebird-sql", + Type: "firebird-sql", Source: "my-fdb-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -150,15 +146,12 @@ func TestParseFromYamlWithTemplateParamsFirebird(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments.go b/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments.go index 2878116045b2..dc884328bfd2 100644 --- a/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments.go +++ b/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments.go @@ -27,14 +27,14 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firestore-add-documents" +const resourceType string = "firestore-add-documents" const collectionPathKey string = "collectionPath" const documentDataKey string = "documentData" const returnDocumentDataKey string = "returnData" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -129,7 +129,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -191,3 +191,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments_test.go b/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments_test.go index 5e743714f172..62ad017c7d13 100644 --- a/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments_test.go +++ b/internal/tools/firestore/firestoreadddocuments/firestoreadddocuments_test.go @@ -17,7 +17,6 @@ package firestoreadddocuments_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreAddDocuments(t *testing.T) { { desc: "basic example", in: ` - tools: - add_docs_tool: - kind: firestore-add-documents - source: my-firestore-instance - description: Add documents to Firestore collections + kind: tools + name: add_docs_tool + type: firestore-add-documents + source: my-firestore-instance + description: Add documents to Firestore collections `, want: server.ToolConfigs{ "add_docs_tool": firestoreadddocuments.Config{ Name: "add_docs_tool", - Kind: "firestore-add-documents", + Type: "firestore-add-documents", Source: "my-firestore-instance", Description: "Add documents to Firestore collections", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreAddDocuments(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_add_docs: - kind: firestore-add-documents - source: prod-firestore - description: Add documents with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_add_docs + type: firestore-add-documents + source: prod-firestore + description: Add documents with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_add_docs": firestoreadddocuments.Config{ Name: "secure_add_docs", - Kind: "firestore-add-documents", + Type: "firestore-add-documents", Source: "prod-firestore", Description: "Add documents with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreAddDocuments(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,57 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - add_user_docs: - kind: firestore-add-documents - source: users-firestore - description: Add user documents - authRequired: - - user-auth - add_product_docs: - kind: firestore-add-documents - source: products-firestore - description: Add product documents - add_order_docs: - kind: firestore-add-documents - source: orders-firestore - description: Add order documents - authRequired: - - user-auth - - admin-auth + kind: tools + name: add_user_docs + type: firestore-add-documents + source: users-firestore + description: Add user documents + authRequired: + - user-auth +--- + kind: tools + name: add_product_docs + type: firestore-add-documents + source: products-firestore + description: Add product documents +--- + kind: tools + name: add_order_docs + type: firestore-add-documents + source: orders-firestore + description: Add order documents + authRequired: + - user-auth + - admin-auth ` want := server.ToolConfigs{ "add_user_docs": firestoreadddocuments.Config{ Name: "add_user_docs", - Kind: "firestore-add-documents", + Type: "firestore-add-documents", Source: "users-firestore", Description: "Add user documents", AuthRequired: []string{"user-auth"}, }, "add_product_docs": firestoreadddocuments.Config{ Name: "add_product_docs", - Kind: "firestore-add-documents", + Type: "firestore-add-documents", Source: "products-firestore", Description: "Add product documents", AuthRequired: []string{}, }, "add_order_docs": firestoreadddocuments.Config{ Name: "add_order_docs", - Kind: "firestore-add-documents", + Type: "firestore-add-documents", Source: "orders-firestore", Description: "Add order documents", AuthRequired: []string{"user-auth", "admin-auth"}, }, } - - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments.go b/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments.go index f92780d616ac..f0a3bd0c8048 100644 --- a/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments.go +++ b/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments.go @@ -27,12 +27,12 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firestore-delete-documents" +const resourceType string = "firestore-delete-documents" const documentPathsKey string = "documentPaths" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -95,7 +95,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -156,3 +156,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments_test.go b/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments_test.go index 15cfce822c24..fe02e2d6c2d4 100644 --- a/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments_test.go +++ b/internal/tools/firestore/firestoredeletedocuments/firestoredeletedocuments_test.go @@ -17,7 +17,6 @@ package firestoredeletedocuments_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreDeleteDocuments(t *testing.T) { { desc: "basic example", in: ` - tools: - delete_docs_tool: - kind: firestore-delete-documents - source: my-firestore-instance - description: Delete documents from Firestore by paths + kind: tools + name: delete_docs_tool + type: firestore-delete-documents + source: my-firestore-instance + description: Delete documents from Firestore by paths `, want: server.ToolConfigs{ "delete_docs_tool": firestoredeletedocuments.Config{ Name: "delete_docs_tool", - Kind: "firestore-delete-documents", + Type: "firestore-delete-documents", Source: "my-firestore-instance", Description: "Delete documents from Firestore by paths", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreDeleteDocuments(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_delete_docs: - kind: firestore-delete-documents - source: prod-firestore - description: Delete documents with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_delete_docs + type: firestore-delete-documents + source: prod-firestore + description: Delete documents with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_delete_docs": firestoredeletedocuments.Config{ Name: "secure_delete_docs", - Kind: "firestore-delete-documents", + Type: "firestore-delete-documents", Source: "prod-firestore", Description: "Delete documents with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreDeleteDocuments(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - delete_user_docs: - kind: firestore-delete-documents - source: users-firestore - description: Delete user documents - authRequired: - - user-auth - delete_product_docs: - kind: firestore-delete-documents - source: products-firestore - description: Delete product documents - delete_order_docs: - kind: firestore-delete-documents - source: orders-firestore - description: Delete order documents - authRequired: - - user-auth - - admin-auth + kind: tools + name: delete_user_docs + type: firestore-delete-documents + source: users-firestore + description: Delete user documents + authRequired: + - user-auth +--- + kind: tools + name: delete_product_docs + type: firestore-delete-documents + source: products-firestore + description: Delete product documents +--- + kind: tools + name: delete_order_docs + type: firestore-delete-documents + source: orders-firestore + description: Delete order documents + authRequired: + - user-auth + - admin-auth ` want := server.ToolConfigs{ "delete_user_docs": firestoredeletedocuments.Config{ Name: "delete_user_docs", - Kind: "firestore-delete-documents", + Type: "firestore-delete-documents", Source: "users-firestore", Description: "Delete user documents", AuthRequired: []string{"user-auth"}, }, "delete_product_docs": firestoredeletedocuments.Config{ Name: "delete_product_docs", - Kind: "firestore-delete-documents", + Type: "firestore-delete-documents", Source: "products-firestore", Description: "Delete product documents", AuthRequired: []string{}, }, "delete_order_docs": firestoredeletedocuments.Config{ Name: "delete_order_docs", - Kind: "firestore-delete-documents", + Type: "firestore-delete-documents", Source: "orders-firestore", Description: "Delete order documents", AuthRequired: []string{"user-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments.go b/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments.go index 42e6cb86e972..3d68c4170ba7 100644 --- a/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments.go +++ b/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments.go @@ -27,12 +27,12 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firestore-get-documents" +const resourceType string = "firestore-get-documents" const documentPathsKey string = "documentPaths" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -95,7 +95,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -157,3 +157,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments_test.go b/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments_test.go index 4cc6ab62452e..5a44b9d6872a 100644 --- a/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments_test.go +++ b/internal/tools/firestore/firestoregetdocuments/firestoregetdocuments_test.go @@ -17,7 +17,6 @@ package firestoregetdocuments_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreGetDocuments(t *testing.T) { { desc: "basic example", in: ` - tools: - get_docs_tool: - kind: firestore-get-documents - source: my-firestore-instance - description: Retrieve documents from Firestore by paths + kind: tools + name: get_docs_tool + type: firestore-get-documents + source: my-firestore-instance + description: Retrieve documents from Firestore by paths `, want: server.ToolConfigs{ "get_docs_tool": firestoregetdocuments.Config{ Name: "get_docs_tool", - Kind: "firestore-get-documents", + Type: "firestore-get-documents", Source: "my-firestore-instance", Description: "Retrieve documents from Firestore by paths", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreGetDocuments(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_get_docs: - kind: firestore-get-documents - source: prod-firestore - description: Get documents with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_get_docs + type: firestore-get-documents + source: prod-firestore + description: Get documents with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_get_docs": firestoregetdocuments.Config{ Name: "secure_get_docs", - Kind: "firestore-get-documents", + Type: "firestore-get-documents", Source: "prod-firestore", Description: "Get documents with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreGetDocuments(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - get_user_docs: - kind: firestore-get-documents - source: users-firestore - description: Get user documents - authRequired: - - user-auth - get_product_docs: - kind: firestore-get-documents - source: products-firestore - description: Get product documents - get_order_docs: - kind: firestore-get-documents - source: orders-firestore - description: Get order documents - authRequired: - - user-auth - - admin-auth + kind: tools + name: get_user_docs + type: firestore-get-documents + source: users-firestore + description: Get user documents + authRequired: + - user-auth +--- + kind: tools + name: get_product_docs + type: firestore-get-documents + source: products-firestore + description: Get product documents +--- + kind: tools + name: get_order_docs + type: firestore-get-documents + source: orders-firestore + description: Get order documents + authRequired: + - user-auth + - admin-auth ` want := server.ToolConfigs{ "get_user_docs": firestoregetdocuments.Config{ Name: "get_user_docs", - Kind: "firestore-get-documents", + Type: "firestore-get-documents", Source: "users-firestore", Description: "Get user documents", AuthRequired: []string{"user-auth"}, }, "get_product_docs": firestoregetdocuments.Config{ Name: "get_product_docs", - Kind: "firestore-get-documents", + Type: "firestore-get-documents", Source: "products-firestore", Description: "Get product documents", AuthRequired: []string{}, }, "get_order_docs": firestoregetdocuments.Config{ Name: "get_order_docs", - Kind: "firestore-get-documents", + Type: "firestore-get-documents", Source: "orders-firestore", Description: "Get order documents", AuthRequired: []string{"user-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestoregetrules/firestoregetrules.go b/internal/tools/firestore/firestoregetrules/firestoregetrules.go index d153130e18de..bfa8b08ba207 100644 --- a/internal/tools/firestore/firestoregetrules/firestoregetrules.go +++ b/internal/tools/firestore/firestoregetrules/firestoregetrules.go @@ -26,11 +26,11 @@ import ( "google.golang.org/api/firebaserules/v1" ) -const kind string = "firestore-get-rules" +const resourceType string = "firestore-get-rules" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -93,7 +93,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -127,3 +127,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestoregetrules/firestoregetrules_test.go b/internal/tools/firestore/firestoregetrules/firestoregetrules_test.go index 405eb1377a2d..c4a7dfb6bb67 100644 --- a/internal/tools/firestore/firestoregetrules/firestoregetrules_test.go +++ b/internal/tools/firestore/firestoregetrules/firestoregetrules_test.go @@ -17,7 +17,6 @@ package firestoregetrules_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreGetRules(t *testing.T) { { desc: "basic example", in: ` - tools: - get_rules_tool: - kind: firestore-get-rules - source: my-firestore-instance - description: Retrieves the active Firestore security rules for the current project + kind: tools + name: get_rules_tool + type: firestore-get-rules + source: my-firestore-instance + description: Retrieves the active Firestore security rules for the current project `, want: server.ToolConfigs{ "get_rules_tool": firestoregetrules.Config{ Name: "get_rules_tool", - Kind: "firestore-get-rules", + Type: "firestore-get-rules", Source: "my-firestore-instance", Description: "Retrieves the active Firestore security rules for the current project", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreGetRules(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_get_rules: - kind: firestore-get-rules - source: prod-firestore - description: Get Firestore security rules with authentication - authRequired: - - google-auth-service - - admin-service + kind: tools + name: secure_get_rules + type: firestore-get-rules + source: prod-firestore + description: Get Firestore security rules with authentication + authRequired: + - google-auth-service + - admin-service `, want: server.ToolConfigs{ "secure_get_rules": firestoregetrules.Config{ Name: "secure_get_rules", - Kind: "firestore-get-rules", + Type: "firestore-get-rules", Source: "prod-firestore", Description: "Get Firestore security rules with authentication", AuthRequired: []string{"google-auth-service", "admin-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreGetRules(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - get_dev_rules: - kind: firestore-get-rules - source: dev-firestore - description: Get development Firestore rules - authRequired: - - dev-auth - get_staging_rules: - kind: firestore-get-rules - source: staging-firestore - description: Get staging Firestore rules - get_prod_rules: - kind: firestore-get-rules - source: prod-firestore - description: Get production Firestore rules - authRequired: - - prod-auth - - admin-auth + kind: tools + name: get_dev_rules + type: firestore-get-rules + source: dev-firestore + description: Get development Firestore rules + authRequired: + - dev-auth +--- + kind: tools + name: get_staging_rules + type: firestore-get-rules + source: staging-firestore + description: Get staging Firestore rules +--- + kind: tools + name: get_prod_rules + type: firestore-get-rules + source: prod-firestore + description: Get production Firestore rules + authRequired: + - prod-auth + - admin-auth ` want := server.ToolConfigs{ "get_dev_rules": firestoregetrules.Config{ Name: "get_dev_rules", - Kind: "firestore-get-rules", + Type: "firestore-get-rules", Source: "dev-firestore", Description: "Get development Firestore rules", AuthRequired: []string{"dev-auth"}, }, "get_staging_rules": firestoregetrules.Config{ Name: "get_staging_rules", - Kind: "firestore-get-rules", + Type: "firestore-get-rules", Source: "staging-firestore", Description: "Get staging Firestore rules", AuthRequired: []string{}, }, "get_prod_rules": firestoregetrules.Config{ Name: "get_prod_rules", - Kind: "firestore-get-rules", + Type: "firestore-get-rules", Source: "prod-firestore", Description: "Get production Firestore rules", AuthRequired: []string{"prod-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestorelistcollections/firestorelistcollections.go b/internal/tools/firestore/firestorelistcollections/firestorelistcollections.go index 4e09600e730a..ff6927594a09 100644 --- a/internal/tools/firestore/firestorelistcollections/firestorelistcollections.go +++ b/internal/tools/firestore/firestorelistcollections/firestorelistcollections.go @@ -27,12 +27,12 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firestore-list-collections" +const resourceType string = "firestore-list-collections" const parentPathKey string = "parentPath" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -96,7 +96,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -141,3 +141,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestorelistcollections/firestorelistcollections_test.go b/internal/tools/firestore/firestorelistcollections/firestorelistcollections_test.go index d3b08ae64972..1b8b374a8efe 100644 --- a/internal/tools/firestore/firestorelistcollections/firestorelistcollections_test.go +++ b/internal/tools/firestore/firestorelistcollections/firestorelistcollections_test.go @@ -17,7 +17,6 @@ package firestorelistcollections_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreListCollections(t *testing.T) { { desc: "basic example", in: ` - tools: - list_collections_tool: - kind: firestore-list-collections - source: my-firestore-instance - description: List collections in Firestore + kind: tools + name: list_collections_tool + type: firestore-list-collections + source: my-firestore-instance + description: List collections in Firestore `, want: server.ToolConfigs{ "list_collections_tool": firestorelistcollections.Config{ Name: "list_collections_tool", - Kind: "firestore-list-collections", + Type: "firestore-list-collections", Source: "my-firestore-instance", Description: "List collections in Firestore", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreListCollections(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_list_collections: - kind: firestore-list-collections - source: prod-firestore - description: List collections with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_list_collections + type: firestore-list-collections + source: prod-firestore + description: List collections with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_list_collections": firestorelistcollections.Config{ Name: "secure_list_collections", - Kind: "firestore-list-collections", + Type: "firestore-list-collections", Source: "prod-firestore", Description: "List collections with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreListCollections(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - list_user_collections: - kind: firestore-list-collections - source: users-firestore - description: List user-related collections - authRequired: - - user-auth - list_product_collections: - kind: firestore-list-collections - source: products-firestore - description: List product-related collections - list_admin_collections: - kind: firestore-list-collections - source: admin-firestore - description: List administrative collections - authRequired: - - user-auth - - admin-auth + kind: tools + name: list_user_collections + type: firestore-list-collections + source: users-firestore + description: List user-related collections + authRequired: + - user-auth +--- + kind: tools + name: list_product_collections + type: firestore-list-collections + source: products-firestore + description: List product-related collections +--- + kind: tools + name: list_admin_collections + type: firestore-list-collections + source: admin-firestore + description: List administrative collections + authRequired: + - user-auth + - admin-auth ` want := server.ToolConfigs{ "list_user_collections": firestorelistcollections.Config{ Name: "list_user_collections", - Kind: "firestore-list-collections", + Type: "firestore-list-collections", Source: "users-firestore", Description: "List user-related collections", AuthRequired: []string{"user-auth"}, }, "list_product_collections": firestorelistcollections.Config{ Name: "list_product_collections", - Kind: "firestore-list-collections", + Type: "firestore-list-collections", Source: "products-firestore", Description: "List product-related collections", AuthRequired: []string{}, }, "list_admin_collections": firestorelistcollections.Config{ Name: "list_admin_collections", - Kind: "firestore-list-collections", + Type: "firestore-list-collections", Source: "admin-firestore", Description: "List administrative collections", AuthRequired: []string{"user-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestorequery/firestorequery.go b/internal/tools/firestore/firestorequery/firestorequery.go index 3501d52b5b8e..2868dd87f1cb 100644 --- a/internal/tools/firestore/firestorequery/firestorequery.go +++ b/internal/tools/firestore/firestorequery/firestorequery.go @@ -32,13 +32,13 @@ import ( // Constants for tool configuration const ( - kind = "firestore-query" + resourceType = "firestore-query" defaultLimit = 100 ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -60,7 +60,7 @@ type compatibleSource interface { // Config represents the configuration for the Firestore query tool type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -80,9 +80,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of tool configuration -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of tool configuration +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance from the configuration @@ -159,7 +159,7 @@ var validOperators = map[string]bool{ // Invoke executes the Firestore query based on the provided parameters func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -406,3 +406,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestorequery/firestorequery_test.go b/internal/tools/firestore/firestorequery/firestorequery_test.go index 178bbe8071bc..380b1b26d152 100644 --- a/internal/tools/firestore/firestorequery/firestorequery_test.go +++ b/internal/tools/firestore/firestorequery/firestorequery_test.go @@ -17,7 +17,6 @@ package firestorequery_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,22 +37,22 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { { desc: "basic example with parameterized collection path", in: ` - tools: - query_users_tool: - kind: firestore-query - source: my-firestore-instance - description: Query users collection with parameterized path - collectionPath: "users/{{.userId}}/documents" - parameters: - - name: userId - type: string - description: The user ID to query documents for - required: true + kind: tools + name: query_users_tool + type: firestore-query + source: my-firestore-instance + description: Query users collection with parameterized path + collectionPath: "users/{{.userId}}/documents" + parameters: + - name: userId + type: string + description: The user ID to query documents for + required: true `, want: server.ToolConfigs{ "query_users_tool": firestorequery.Config{ Name: "query_users_tool", - Kind: "firestore-query", + Type: "firestore-query", Source: "my-firestore-instance", Description: "Query users collection with parameterized path", CollectionPath: "users/{{.userId}}/documents", @@ -67,41 +66,41 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { { desc: "with parameterized filters", in: ` - tools: - query_products_tool: - kind: firestore-query - source: prod-firestore - description: Query products with dynamic filters - collectionPath: "products" - filters: | - { - "and": [ - {"field": "category", "op": "==", "value": {"stringValue": "{{.category}}"}}, - {"field": "price", "op": "<=", "value": {"doubleValue": {{.maxPrice}}}} - ] - } - parameters: - - name: category - type: string - description: Product category to filter by - required: true - - name: maxPrice - type: float - description: Maximum price for products - required: true + kind: tools + name: query_products_tool + type: firestore-query + source: prod-firestore + description: Query products with dynamic filters + collectionPath: "products" + filters: | + { + "and": [ + {"field": "category", "op": "==", "value": {"stringValue": "{{.category}}"}}, + {"field": "price", "op": "<=", "value": {"doubleValue": {{.maxPrice}}}} + ] + } + parameters: + - name: category + type: string + description: Product category to filter by + required: true + - name: maxPrice + type: float + description: Maximum price for products + required: true `, want: server.ToolConfigs{ "query_products_tool": firestorequery.Config{ Name: "query_products_tool", - Kind: "firestore-query", + Type: "firestore-query", Source: "prod-firestore", Description: "Query products with dynamic filters", CollectionPath: "products", Filters: `{ - "and": [ - {"field": "category", "op": "==", "value": {"stringValue": "{{.category}}"}}, - {"field": "price", "op": "<=", "value": {"doubleValue": {{.maxPrice}}}} - ] + "and": [ + {"field": "category", "op": "==", "value": {"stringValue": "{{.category}}"}}, + {"field": "price", "op": "<=", "value": {"doubleValue": {{.maxPrice}}}} + ] } `, AuthRequired: []string{}, @@ -115,30 +114,30 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { { desc: "with select fields and orderBy", in: ` - tools: - query_orders_tool: - kind: firestore-query - source: orders-firestore - description: Query orders with field selection - collectionPath: "orders" - select: - - orderId - - customerName - - totalAmount - orderBy: - field: "{{.sortField}}" - direction: "DESCENDING" - limit: 50 - parameters: - - name: sortField - type: string - description: Field to sort by - required: true + kind: tools + name: query_orders_tool + type: firestore-query + source: orders-firestore + description: Query orders with field selection + collectionPath: "orders" + select: + - orderId + - customerName + - totalAmount + orderBy: + field: "{{.sortField}}" + direction: "DESCENDING" + limit: 50 + parameters: + - name: sortField + type: string + description: Field to sort by + required: true `, want: server.ToolConfigs{ "query_orders_tool": firestorequery.Config{ Name: "query_orders_tool", - Kind: "firestore-query", + Type: "firestore-query", Source: "orders-firestore", Description: "Query orders with field selection", CollectionPath: "orders", @@ -158,59 +157,59 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { { desc: "with auth requirements and complex filters", in: ` - tools: - secure_query_tool: - kind: firestore-query - source: secure-firestore - description: Query with authentication and complex filters - collectionPath: "{{.collection}}" - filters: | - { - "or": [ - { - "and": [ - {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, - {"field": "priority", "op": ">=", "value": {"integerValue": "{{.minPriority}}"}} - ] - }, - {"field": "urgent", "op": "==", "value": {"booleanValue": true}} - ] - } - analyzeQuery: true - authRequired: - - google-auth-service - - api-key-service - parameters: - - name: collection - type: string - description: Collection name to query - required: true - - name: status - type: string - description: Status to filter by - required: true - - name: minPriority - type: integer - description: Minimum priority level - default: 1 + kind: tools + name: secure_query_tool + type: firestore-query + source: secure-firestore + description: Query with authentication and complex filters + collectionPath: "{{.collection}}" + filters: | + { + "or": [ + { + "and": [ + {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, + {"field": "priority", "op": ">=", "value": {"integerValue": "{{.minPriority}}"}} + ] + }, + {"field": "urgent", "op": "==", "value": {"booleanValue": true}} + ] + } + analyzeQuery: true + authRequired: + - google-auth-service + - api-key-service + parameters: + - name: collection + type: string + description: Collection name to query + required: true + - name: status + type: string + description: Status to filter by + required: true + - name: minPriority + type: integer + description: Minimum priority level + default: 1 `, want: server.ToolConfigs{ "secure_query_tool": firestorequery.Config{ Name: "secure_query_tool", - Kind: "firestore-query", + Type: "firestore-query", Source: "secure-firestore", Description: "Query with authentication and complex filters", CollectionPath: "{{.collection}}", Filters: `{ - "or": [ - { - "and": [ - {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, - {"field": "priority", "op": ">=", "value": {"integerValue": "{{.minPriority}}"}} - ] - }, - {"field": "urgent", "op": "==", "value": {"booleanValue": true}} - ] + "or": [ + { + "and": [ + {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}}, + {"field": "priority", "op": ">=", "value": {"integerValue": "{{.minPriority}}"}} + ] + }, + {"field": "urgent", "op": "==", "value": {"booleanValue": true}} + ] } `, AnalyzeQuery: true, @@ -226,71 +225,71 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { { desc: "with Firestore native JSON value types and template parameters", in: ` - tools: - query_with_typed_values: - kind: firestore-query - source: typed-firestore - description: Query with Firestore native JSON value types - collectionPath: "countries" - filters: | - { - "or": [ - {"field": "continent", "op": "==", "value": {"stringValue": "{{.continent}}"}}, - { - "and": [ - {"field": "area", "op": ">", "value": {"integerValue": "2000000"}}, - {"field": "area", "op": "<", "value": {"integerValue": "3000000"}}, - {"field": "population", "op": ">=", "value": {"integerValue": "{{.minPopulation}}"}}, - {"field": "gdp", "op": ">", "value": {"doubleValue": {{.minGdp}}}}, - {"field": "isActive", "op": "==", "value": {"booleanValue": {{.isActive}}}}, - {"field": "lastUpdated", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} - ] - } - ] - } - parameters: - - name: continent - type: string - description: Continent to filter by - required: true - - name: minPopulation - type: string - description: Minimum population as string - required: true - - name: minGdp - type: float - description: Minimum GDP value - required: true - - name: isActive - type: boolean - description: Filter by active status - required: true - - name: startDate - type: string - description: Start date in RFC3339 format - required: true + kind: tools + name: query_with_typed_values + type: firestore-query + source: typed-firestore + description: Query with Firestore native JSON value types + collectionPath: "countries" + filters: | + { + "or": [ + {"field": "continent", "op": "==", "value": {"stringValue": "{{.continent}}"}}, + { + "and": [ + {"field": "area", "op": ">", "value": {"integerValue": "2000000"}}, + {"field": "area", "op": "<", "value": {"integerValue": "3000000"}}, + {"field": "population", "op": ">=", "value": {"integerValue": "{{.minPopulation}}"}}, + {"field": "gdp", "op": ">", "value": {"doubleValue": {{.minGdp}}}}, + {"field": "isActive", "op": "==", "value": {"booleanValue": {{.isActive}}}}, + {"field": "lastUpdated", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} + ] + } + ] + } + parameters: + - name: continent + type: string + description: Continent to filter by + required: true + - name: minPopulation + type: string + description: Minimum population as string + required: true + - name: minGdp + type: float + description: Minimum GDP value + required: true + - name: isActive + type: boolean + description: Filter by active status + required: true + - name: startDate + type: string + description: Start date in RFC3339 format + required: true `, want: server.ToolConfigs{ "query_with_typed_values": firestorequery.Config{ Name: "query_with_typed_values", - Kind: "firestore-query", + Type: "firestore-query", Source: "typed-firestore", Description: "Query with Firestore native JSON value types", CollectionPath: "countries", Filters: `{ - "or": [ - {"field": "continent", "op": "==", "value": {"stringValue": "{{.continent}}"}}, - { - "and": [ - {"field": "area", "op": ">", "value": {"integerValue": "2000000"}}, - {"field": "area", "op": "<", "value": {"integerValue": "3000000"}}, - {"field": "population", "op": ">=", "value": {"integerValue": "{{.minPopulation}}"}}, - {"field": "gdp", "op": ">", "value": {"doubleValue": {{.minGdp}}}}, - {"field": "isActive", "op": "==", "value": {"booleanValue": {{.isActive}}}}, - {"field": "lastUpdated", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} - ] - } - ] + "or": [ + {"field": "continent", "op": "==", "value": {"stringValue": "{{.continent}}"}}, + { + "and": [ + {"field": "area", "op": ">", "value": {"integerValue": "2000000"}}, + {"field": "area", "op": "<", "value": {"integerValue": "3000000"}}, + {"field": "population", "op": ">=", "value": {"integerValue": "{{.minPopulation}}"}}, + {"field": "gdp", "op": ">", "value": {"doubleValue": {{.minGdp}}}}, + {"field": "isActive", "op": "==", "value": {"booleanValue": {{.isActive}}}}, + {"field": "lastUpdated", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} + ] + } + ] } `, AuthRequired: []string{}, @@ -307,15 +306,12 @@ func TestParseFromYamlFirestoreQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -328,94 +324,98 @@ func TestParseFromYamlMultipleQueryTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - query_user_posts: - kind: firestore-query - source: social-firestore - description: Query user posts with filtering - collectionPath: "users/{{.userId}}/posts" - filters: | - { - "and": [ - {"field": "visibility", "op": "==", "value": {"stringValue": "{{.visibility}}"}}, - {"field": "createdAt", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} - ] - } - select: - - title - - content - - likes - orderBy: - field: createdAt - direction: "{{.sortOrder}}" - limit: 20 - parameters: - - name: userId - type: string - description: User ID whose posts to query - required: true - - name: visibility - type: string - description: Post visibility (public, private, friends) - required: true - - name: startDate - type: string - description: Start date for posts - required: true - - name: sortOrder - type: string - description: Sort order (ASCENDING or DESCENDING) - default: "DESCENDING" - query_inventory: - kind: firestore-query - source: inventory-firestore - description: Query inventory items - collectionPath: "warehouses/{{.warehouseId}}/inventory" - filters: | - { - "field": "quantity", "op": "<", "value": {"integerValue": "{{.threshold}}"}} - parameters: - - name: warehouseId - type: string - description: Warehouse ID to check inventory - required: true - - name: threshold - type: integer - description: Quantity threshold for low stock - required: true - query_transactions: - kind: firestore-query - source: finance-firestore - description: Query financial transactions - collectionPath: "accounts/{{.accountId}}/transactions" - filters: | - { - "or": [ - {"field": "type", "op": "==", "value": {"stringValue": "{{.transactionType}}"}}, - {"field": "amount", "op": ">", "value": {"doubleValue": {{.minAmount}}}} - ] - } - analyzeQuery: true - authRequired: - - finance-auth - parameters: - - name: accountId - type: string - description: Account ID for transactions - required: true - - name: transactionType - type: string - description: Type of transaction - default: "all" - - name: minAmount - type: float - description: Minimum transaction amount - default: 0 + kind: tools + name: query_user_posts + type: firestore-query + source: social-firestore + description: Query user posts with filtering + collectionPath: "users/{{.userId}}/posts" + filters: | + { + "and": [ + {"field": "visibility", "op": "==", "value": {"stringValue": "{{.visibility}}"}}, + {"field": "createdAt", "op": ">=", "value": {"timestampValue": "{{.startDate}}"}} + ] + } + select: + - title + - content + - likes + orderBy: + field: createdAt + direction: "{{.sortOrder}}" + limit: 20 + parameters: + - name: userId + type: string + description: User ID whose posts to query + required: true + - name: visibility + type: string + description: Post visibility (public, private, friends) + required: true + - name: startDate + type: string + description: Start date for posts + required: true + - name: sortOrder + type: string + description: Sort order (ASCENDING or DESCENDING) + default: "DESCENDING" +--- + kind: tools + name: query_inventory + type: firestore-query + source: inventory-firestore + description: Query inventory items + collectionPath: "warehouses/{{.warehouseId}}/inventory" + filters: | + { + "field": "quantity", "op": "<", "value": {"integerValue": "{{.threshold}}"}} + parameters: + - name: warehouseId + type: string + description: Warehouse ID to check inventory + required: true + - name: threshold + type: integer + description: Quantity threshold for low stock + required: true +--- + kind: tools + name: query_transactions + type: firestore-query + source: finance-firestore + description: Query financial transactions + collectionPath: "accounts/{{.accountId}}/transactions" + filters: | + { + "or": [ + {"field": "type", "op": "==", "value": {"stringValue": "{{.transactionType}}"}}, + {"field": "amount", "op": ">", "value": {"doubleValue": {{.minAmount}}}} + ] + } + analyzeQuery: true + authRequired: + - finance-auth + parameters: + - name: accountId + type: string + description: Account ID for transactions + required: true + - name: transactionType + type: string + description: Type of transaction + default: "all" + - name: minAmount + type: float + description: Minimum transaction amount + default: 0 ` want := server.ToolConfigs{ "query_user_posts": firestorequery.Config{ Name: "query_user_posts", - Kind: "firestore-query", + Type: "firestore-query", Source: "social-firestore", Description: "Query user posts with filtering", CollectionPath: "users/{{.userId}}/posts", @@ -442,7 +442,7 @@ func TestParseFromYamlMultipleQueryTools(t *testing.T) { }, "query_inventory": firestorequery.Config{ Name: "query_inventory", - Kind: "firestore-query", + Type: "firestore-query", Source: "inventory-firestore", Description: "Query inventory items", CollectionPath: "warehouses/{{.warehouseId}}/inventory", @@ -457,7 +457,7 @@ func TestParseFromYamlMultipleQueryTools(t *testing.T) { }, "query_transactions": firestorequery.Config{ Name: "query_transactions", - Kind: "firestore-query", + Type: "firestore-query", Source: "finance-firestore", Description: "Query financial transactions", CollectionPath: "accounts/{{.accountId}}/transactions", @@ -478,15 +478,11 @@ func TestParseFromYamlMultipleQueryTools(t *testing.T) { }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestorequerycollection/firestorequerycollection.go b/internal/tools/firestore/firestorequerycollection/firestorequerycollection.go index f4c6aa493c4e..2a9867b1e7f6 100644 --- a/internal/tools/firestore/firestorequerycollection/firestorequerycollection.go +++ b/internal/tools/firestore/firestorequerycollection/firestorequerycollection.go @@ -31,7 +31,7 @@ import ( // Constants for tool configuration const ( - kind = "firestore-query-collection" + resourceType = "firestore-query-collection" defaultLimit = 100 defaultAnalyze = false maxFilterLength = 100 // Maximum filters to prevent abuse @@ -73,8 +73,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -96,7 +96,7 @@ type compatibleSource interface { // Config represents the configuration for the Firestore query collection tool type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -105,9 +105,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of tool configuration -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of tool configuration +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance from the configuration @@ -231,7 +231,7 @@ func (o *OrderByConfig) GetDirection() firestoreapi.Direction { // Invoke executes the Firestore query based on the provided parameters func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -419,3 +419,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestorequerycollection/firestorequerycollection_test.go b/internal/tools/firestore/firestorequerycollection/firestorequerycollection_test.go index 355ce8e188b7..450ad18016bc 100644 --- a/internal/tools/firestore/firestorequerycollection/firestorequerycollection_test.go +++ b/internal/tools/firestore/firestorequerycollection/firestorequerycollection_test.go @@ -17,7 +17,6 @@ package firestorequerycollection_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreQueryCollection(t *testing.T) { { desc: "basic example", in: ` - tools: - query_users_tool: - kind: firestore-query-collection - source: my-firestore-instance - description: Query users collection with filters and ordering + kind: tools + name: query_users_tool + type: firestore-query-collection + source: my-firestore-instance + description: Query users collection with filters and ordering `, want: server.ToolConfigs{ "query_users_tool": firestorequerycollection.Config{ Name: "query_users_tool", - Kind: "firestore-query-collection", + Type: "firestore-query-collection", Source: "my-firestore-instance", Description: "Query users collection with filters and ordering", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreQueryCollection(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_query_tool: - kind: firestore-query-collection - source: prod-firestore - description: Query collections with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_query_tool + type: firestore-query-collection + source: prod-firestore + description: Query collections with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_query_tool": firestorequerycollection.Config{ Name: "secure_query_tool", - Kind: "firestore-query-collection", + Type: "firestore-query-collection", Source: "prod-firestore", Description: "Query collections with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,12 @@ func TestParseFromYamlFirestoreQueryCollection(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +95,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - query_users: - kind: firestore-query-collection - source: users-firestore - description: Query user documents with filtering - authRequired: - - user-auth - query_products: - kind: firestore-query-collection - source: products-firestore - description: Query product catalog - query_orders: - kind: firestore-query-collection - source: orders-firestore - description: Query customer orders with complex filters - authRequired: - - user-auth - - admin-auth + kind: tools + name: query_users + type: firestore-query-collection + source: users-firestore + description: Query user documents with filtering + authRequired: + - user-auth +--- + kind: tools + name: query_products + type: firestore-query-collection + source: products-firestore + description: Query product catalog +--- + kind: tools + name: query_orders + type: firestore-query-collection + source: orders-firestore + description: Query customer orders with complex filters + authRequired: + - user-auth + - admin-auth ` want := server.ToolConfigs{ "query_users": firestorequerycollection.Config{ Name: "query_users", - Kind: "firestore-query-collection", + Type: "firestore-query-collection", Source: "users-firestore", Description: "Query user documents with filtering", AuthRequired: []string{"user-auth"}, }, "query_products": firestorequerycollection.Config{ Name: "query_products", - Kind: "firestore-query-collection", + Type: "firestore-query-collection", Source: "products-firestore", Description: "Query product catalog", AuthRequired: []string{}, }, "query_orders": firestorequerycollection.Config{ Name: "query_orders", - Kind: "firestore-query-collection", + Type: "firestore-query-collection", Source: "orders-firestore", Description: "Query customer orders with complex filters", AuthRequired: []string{"user-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument.go b/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument.go index a791de7a1722..76e1a7efcfb2 100644 --- a/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument.go +++ b/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument.go @@ -28,15 +28,15 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "firestore-update-document" +const resourceType string = "firestore-update-document" const documentPathKey string = "documentPath" const documentDataKey string = "documentData" const updateMaskKey string = "updateMask" const returnDocumentDataKey string = "returnData" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -139,7 +139,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -277,3 +277,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument_test.go b/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument_test.go index 3311aeb86e8b..73d3b0e803c6 100644 --- a/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument_test.go +++ b/internal/tools/firestore/firestoreupdatedocument/firestoreupdatedocument_test.go @@ -19,10 +19,11 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" + "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources" firestoreds "github.com/googleapis/genai-toolbox/internal/sources/firestore" + "github.com/googleapis/genai-toolbox/internal/testutils" "github.com/googleapis/genai-toolbox/internal/tools" "github.com/googleapis/genai-toolbox/internal/util/parameters" ) @@ -31,59 +32,65 @@ func TestNewConfig(t *testing.T) { tests := []struct { name string yaml string - want Config + want server.ToolConfigs wantErr bool }{ { name: "valid config", yaml: ` -name: test-update-document -kind: firestore-update-document -source: test-firestore -description: Update a document in Firestore -authRequired: - - google-oauth -`, - want: Config{ - Name: "test-update-document", - Kind: "firestore-update-document", - Source: "test-firestore", - Description: "Update a document in Firestore", - AuthRequired: []string{"google-oauth"}, + kind: tools + name: test-update-document + type: firestore-update-document + source: test-firestore + description: Update a document in Firestore + authRequired: + - google-oauth + `, + want: server.ToolConfigs{ + "test-update-document": Config{ + Name: "test-update-document", + Type: "firestore-update-document", + Source: "test-firestore", + Description: "Update a document in Firestore", + AuthRequired: []string{"google-oauth"}, + }, }, wantErr: false, }, { name: "minimal config", yaml: ` -name: test-update-document -kind: firestore-update-document -source: test-firestore -description: Update a document -`, - want: Config{ - Name: "test-update-document", - Kind: "firestore-update-document", - Source: "test-firestore", - Description: "Update a document", + kind: tools + name: test-update-document + type: firestore-update-document + source: test-firestore + description: Update a document + `, + want: server.ToolConfigs{ + "test-update-document": Config{ + Name: "test-update-document", + Type: "firestore-update-document", + Source: "test-firestore", + Description: "Update a document", + AuthRequired: []string{}, + }, }, wantErr: false, }, { name: "invalid yaml", yaml: ` -name: test-update-document -kind: [invalid -`, + kind: tools + name: test-update-document + type: [invalid + `, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - decoder := yaml.NewDecoder(strings.NewReader(tt.yaml)) - got, err := newConfig(context.Background(), "test-update-document", decoder) - + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tt.yaml)) if tt.wantErr { if err == nil { t.Fatalf("expected error but got none") @@ -102,12 +109,12 @@ kind: [invalid } } -func TestConfig_ToolConfigKind(t *testing.T) { +func TestConfig_ToolConfigType(t *testing.T) { cfg := Config{} - got := cfg.ToolConfigKind() + got := cfg.ToolConfigType() want := "firestore-update-document" if got != want { - t.Fatalf("ToolConfigKind() = %v, want %v", got, want) + t.Fatalf("ToolConfigType() = %v, want %v", got, want) } } @@ -123,7 +130,7 @@ func TestConfig_Initialize(t *testing.T) { name: "valid initialization", config: Config{ Name: "test-update-document", - Kind: "firestore-update-document", + Type: "firestore-update-document", Source: "test-firestore", Description: "Update a document", }, @@ -161,8 +168,8 @@ func TestConfig_Initialize(t *testing.T) { if actualTool.Name != tt.config.Name { t.Fatalf("tool.Name = %v, want %v", actualTool.Name, tt.config.Name) } - if actualTool.Kind != "firestore-update-document" { - t.Fatalf("tool.Kind = %v, want %v", actualTool.Kind, "firestore-update-document") + if actualTool.Type != "firestore-update-document" { + t.Fatalf("tool.Type = %v, want %v", actualTool.Type, "firestore-update-document") } if diff := cmp.Diff(tt.config.AuthRequired, actualTool.AuthRequired); diff != "" { t.Fatalf("AuthRequired mismatch (-want +got):\n%s", diff) diff --git a/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules.go b/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules.go index 9442982e02da..e41be2da8835 100644 --- a/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules.go +++ b/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules.go @@ -26,7 +26,7 @@ import ( "google.golang.org/api/firebaserules/v1" ) -const kind string = "firestore-validate-rules" +const resourceType string = "firestore-validate-rules" // Parameter keys const ( @@ -34,8 +34,8 @@ const ( ) func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -107,7 +107,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -149,3 +149,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules_test.go b/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules_test.go index f63945d0781d..f454bb5e3513 100644 --- a/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules_test.go +++ b/internal/tools/firestore/firestorevalidaterules/firestorevalidaterules_test.go @@ -17,7 +17,6 @@ package firestorevalidaterules_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlFirestoreValidateRules(t *testing.T) { { desc: "basic example", in: ` - tools: - validate_rules_tool: - kind: firestore-validate-rules - source: my-firestore-instance - description: Validate Firestore security rules + kind: tools + name: validate_rules_tool + type: firestore-validate-rules + source: my-firestore-instance + description: Validate Firestore security rules `, want: server.ToolConfigs{ "validate_rules_tool": firestorevalidaterules.Config{ Name: "validate_rules_tool", - Kind: "firestore-validate-rules", + Type: "firestore-validate-rules", Source: "my-firestore-instance", Description: "Validate Firestore security rules", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlFirestoreValidateRules(t *testing.T) { { desc: "with auth requirements", in: ` - tools: - secure_validate_rules: - kind: firestore-validate-rules - source: prod-firestore - description: Validate rules with authentication - authRequired: - - google-auth-service - - api-key-service + kind: tools + name: secure_validate_rules + type: firestore-validate-rules + source: prod-firestore + description: Validate rules with authentication + authRequired: + - google-auth-service + - api-key-service `, want: server.ToolConfigs{ "secure_validate_rules": firestorevalidaterules.Config{ Name: "secure_validate_rules", - Kind: "firestore-validate-rules", + Type: "firestore-validate-rules", Source: "prod-firestore", Description: "Validate rules with authentication", AuthRequired: []string{"google-auth-service", "api-key-service"}, @@ -78,15 +77,11 @@ func TestParseFromYamlFirestoreValidateRules(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -99,58 +94,58 @@ func TestParseFromYamlMultipleTools(t *testing.T) { t.Fatalf("unexpected error: %s", err) } in := ` - tools: - validate_dev_rules: - kind: firestore-validate-rules - source: dev-firestore - description: Validate development environment rules - authRequired: - - dev-auth - validate_staging_rules: - kind: firestore-validate-rules - source: staging-firestore - description: Validate staging environment rules - validate_prod_rules: - kind: firestore-validate-rules - source: prod-firestore - description: Validate production environment rules - authRequired: - - prod-auth - - admin-auth + kind: tools + name: validate_dev_rules + type: firestore-validate-rules + source: dev-firestore + description: Validate development environment rules + authRequired: + - dev-auth +--- + kind: tools + name: validate_staging_rules + type: firestore-validate-rules + source: staging-firestore + description: Validate staging environment rules +--- + kind: tools + name: validate_prod_rules + type: firestore-validate-rules + source: prod-firestore + description: Validate production environment rules + authRequired: + - prod-auth + - admin-auth ` want := server.ToolConfigs{ "validate_dev_rules": firestorevalidaterules.Config{ Name: "validate_dev_rules", - Kind: "firestore-validate-rules", + Type: "firestore-validate-rules", Source: "dev-firestore", Description: "Validate development environment rules", AuthRequired: []string{"dev-auth"}, }, "validate_staging_rules": firestorevalidaterules.Config{ Name: "validate_staging_rules", - Kind: "firestore-validate-rules", + Type: "firestore-validate-rules", Source: "staging-firestore", Description: "Validate staging environment rules", AuthRequired: []string{}, }, "validate_prod_rules": firestorevalidaterules.Config{ Name: "validate_prod_rules", - Kind: "firestore-validate-rules", + Type: "firestore-validate-rules", Source: "prod-firestore", Description: "Validate production environment rules", AuthRequired: []string{"prod-auth", "admin-auth"}, }, } - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(want, got.Tools); diff != "" { + if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } } diff --git a/internal/tools/http/http.go b/internal/tools/http/http.go index 6ba9699e2b03..82a3ef1c37f9 100644 --- a/internal/tools/http/http.go +++ b/internal/tools/http/http.go @@ -32,11 +32,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "http" +const resourceType string = "http" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -57,7 +57,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -74,8 +74,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -88,7 +88,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be `http`", kind) + return nil, fmt.Errorf("invalid source for %q tool: source type must be `http`", resourceType) } // Combine Source and Tool headers. @@ -227,7 +227,7 @@ func getHeaders(headerParams parameters.Parameters, defaultHeaders map[string]st } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -287,3 +287,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/http/http_test.go b/internal/tools/http/http_test.go index 62bacbca4da6..2cdb756ee70a 100644 --- a/internal/tools/http/http_test.go +++ b/internal/tools/http/http_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,18 +38,18 @@ func TestParseFromYamlHTTP(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: http - source: my-instance - method: GET - description: some description - path: search - `, + kind: tools + name: example_tool + type: http + source: my-instance + method: GET + description: some description + path: search + `, want: server.ToolConfigs{ "example_tool": http.Config{ Name: "example_tool", - Kind: "http", + Type: "http", Source: "my-instance", Method: "GET", Path: "search", @@ -62,54 +61,54 @@ func TestParseFromYamlHTTP(t *testing.T) { { desc: "advanced example", in: ` - tools: - example_tool: - kind: http - source: my-instance - method: GET - path: "{{.pathParam}}?name=alice&pet=cat" - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - queryParams: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - pathParams: - - name: pathParam - type: string - description: path param - requestBody: | - { - "age": {{.age}}, - "city": "{{.city}}", - "food": {{.food}} - } - bodyParams: - - name: age - type: integer - description: age num - - name: city - type: string - description: city string - headers: - Authorization: API_KEY - Content-Type: application/json - headerParams: - - name: Language - type: string - description: language string + kind: tools + name: example_tool + type: http + source: my-instance + method: GET + path: "{{.pathParam}}?name=alice&pet=cat" + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + queryParams: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + pathParams: + - name: pathParam + type: string + description: path param + requestBody: | + { + "age": {{.age}}, + "city": "{{.city}}", + "food": {{.food}} + } + bodyParams: + - name: age + type: integer + description: age num + - name: city + type: string + description: city string + headers: + Authorization: API_KEY + Content-Type: application/json + headerParams: + - name: Language + type: string + description: language string `, want: server.ToolConfigs{ "example_tool": http.Config{ Name: "example_tool", - Kind: "http", + Type: "http", Source: "my-instance", Method: "GET", Path: "{{.pathParam}}?name=alice&pet=cat", @@ -140,15 +139,11 @@ func TestParseFromYamlHTTP(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -169,55 +164,51 @@ func TestFailParseFromYamlHTTP(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: http - source: my-instance - method: GOT - path: "search?name=alice&pet=cat" - description: some description - authRequired: - - my-google-auth-service - - other-auth-service - queryParams: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - requestBody: | - { - "age": {{.age}}, - "city": "{{.city}}" - } - bodyParams: - - name: age - type: integer - description: age num - - name: city - type: string - description: city string - headers: - Authorization: API_KEY - Content-Type: application/json - headerParams: - - name: Language - type: string - description: language string + kind: tools + name: example_tool + type: http + source: my-instance + method: GOT + path: "search?name=alice&pet=cat" + description: some description + authRequired: + - my-google-auth-service + - other-auth-service + queryParams: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + requestBody: | + { + "age": {{.age}}, + "city": "{{.city}}" + } + bodyParams: + - name: age + type: integer + description: age num + - name: city + type: string + description: city string + headers: + Authorization: API_KEY + Content-Type: application/json + headerParams: + - name: Language + type: string + description: language string `, err: `GOT is not a valid http method`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement.go b/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement.go index 5e354d7fd2a3..fb2d47284659 100644 --- a/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement.go +++ b/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-add-dashboard-element" +const resourceType string = "looker-add-dashboard-element" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -135,7 +135,7 @@ var ( ) func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -261,7 +261,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -273,9 +273,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement_test.go b/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement_test.go index 93c007043f56..0c55ee0f9d4e 100644 --- a/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement_test.go +++ b/internal/tools/looker/lookeradddashboardelement/lookeradddashboardelement_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerAddDashboardElement(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-add-dashboard-element - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-add-dashboard-element + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-add-dashboard-element", + Type: "looker-add-dashboard-element", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerAddDashboardElement(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerAddDashboardElement(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-add-dashboard-element - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-add-dashboard-element + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-add-dashboard-element\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-add-dashboard-element\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-add-dashboard-element\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-add-dashboard-element", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter.go b/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter.go index c6c56f85e2b4..b3999ccdb4b6 100644 --- a/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter.go +++ b/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-add-dashboard-filter" +const resourceType string = "looker-add-dashboard-filter" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -129,7 +129,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -230,7 +230,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -238,9 +238,13 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter_test.go b/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter_test.go index 43f43dc6c6c7..0f95161b67d0 100644 --- a/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter_test.go +++ b/internal/tools/looker/lookeradddashboardfilter/lookeradddashboardfilter_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerAddDashboardFilter(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-add-dashboard-filter - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-add-dashboard-filter + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-add-dashboard-filter", + Type: "looker-add-dashboard-filter", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerAddDashboardFilter(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerAddDashboardFilter(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-add-dashboard-filter - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-add-dashboard-filter + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-add-dashboard-filter\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-add-dashboard-filter\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-add-dashboard-filter\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-add-dashboard-filter", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go b/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go index 94cc18e9605e..e2055b7b48e2 100644 --- a/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go +++ b/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go @@ -34,7 +34,7 @@ import ( "golang.org/x/oauth2" ) -const kind string = "looker-conversational-analytics" +const resourceType string = "looker-conversational-analytics" const instructions = `**INSTRUCTIONS - FOLLOW THESE RULES:** 1. **CONTENT:** Your answer should present the supporting data and then provide a conclusion based on that data. @@ -42,8 +42,8 @@ const instructions = `**INSTRUCTIONS - FOLLOW THESE RULES:** 3. **NO CHARTS:** You are STRICTLY FORBIDDEN from generating any charts, graphs, images, or any other form of visualization.` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -126,7 +126,7 @@ type CAPayload struct { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -136,8 +136,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -150,11 +150,11 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } if s.GoogleCloudProject() == "" { - return nil, fmt.Errorf("project must be defined for source to use with %q tool", kind) + return nil, fmt.Errorf("project must be defined for source to use with %q tool", resourceType) } userQueryParameter := parameters.NewStringParameter("user_query_with_context", "The user's question, potentially including conversation history and system instructions for context.") @@ -216,7 +216,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -309,7 +309,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -561,9 +561,13 @@ func appendMessage(messages []map[string]any, newMessage map[string]any) []map[s } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics_test.go b/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics_test.go index fbc17e47c454..9e0fdb26edcd 100644 --- a/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics_test.go +++ b/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics_test.go @@ -17,7 +17,6 @@ package lookerconversationalanalytics_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlLookerConversationalAnalytics(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-conversational-analytics - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-conversational-analytics + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lookerconversationalanalytics.Config{ Name: "example_tool", - Kind: "looker-conversational-analytics", + Type: "looker-conversational-analytics", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,11 @@ func TestParseFromYamlLookerConversationalAnalytics(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile.go b/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile.go index b65be502efc5..79d2958ee62f 100644 --- a/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile.go +++ b/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-create-project-file" +const resourceType string = "looker-create-project-file" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,9 +181,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile_test.go b/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile_test.go index bd9b910b4dff..d8a90fa390ff 100644 --- a/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile_test.go +++ b/internal/tools/looker/lookercreateprojectfile/lookercreateprojectfile_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerCreateProjectFile(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-create-project-file - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-create-project-file + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-create-project-file", + Type: "looker-create-project-file", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerCreateProjectFile(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerCreateProjectFile(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-create-project-file - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-create-project-file + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-create-project-file\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-create-project-file\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-create-project-file\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-create-project-file", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile.go b/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile.go index b49690c8d375..6748647fe658 100644 --- a/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile.go +++ b/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-delete-project-file" +const resourceType string = "looker-delete-project-file" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -112,7 +112,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -173,9 +173,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile_test.go b/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile_test.go index ff0ab2bf7b81..16f226a9f5cf 100644 --- a/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile_test.go +++ b/internal/tools/looker/lookerdeleteprojectfile/lookerdeleteprojectfile_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerDeleteProjectFile(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-delete-project-file - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-delete-project-file + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-delete-project-file", + Type: "looker-delete-project-file", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerDeleteProjectFile(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerDeleteProjectFile(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-delete-project-file - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-delete-project-file + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-delete-project-file\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-delete-project-file\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-delete-project-file\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-delete-project-file", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerdevmode/lookerdevmode.go b/internal/tools/looker/lookerdevmode/lookerdevmode.go index 46736125cf1d..e46655dcb82f 100644 --- a/internal/tools/looker/lookerdevmode/lookerdevmode.go +++ b/internal/tools/looker/lookerdevmode/lookerdevmode.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-dev-mode" +const resourceType string = "looker-dev-mode" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -109,7 +109,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -163,7 +163,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -175,9 +175,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerdevmode/lookerdevmode_test.go b/internal/tools/looker/lookerdevmode/lookerdevmode_test.go index dd776f77e208..961bb5cb405c 100644 --- a/internal/tools/looker/lookerdevmode/lookerdevmode_test.go +++ b/internal/tools/looker/lookerdevmode/lookerdevmode_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerDevMode(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-dev-mode - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-dev-mode + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-dev-mode", + Type: "looker-dev-mode", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerDevMode(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerDevMode(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-dev-mode - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-dev-mode + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-dev-mode\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-dev-mode\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-dev-mode\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-dev-mode", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl.go b/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl.go index 7a4b9506d3d6..99cf0bf60992 100644 --- a/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl.go +++ b/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-generate-embed-url" +const resourceType string = "looker-generate-embed-url" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -115,7 +115,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -175,7 +175,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -187,9 +187,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl_test.go b/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl_test.go index 93dcd0eb88ac..08aeba23d54d 100644 --- a/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl_test.go +++ b/internal/tools/looker/lookergenerateembedurl/lookergenerateembedurl_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGenerateEmbedUrl(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-generate-embed-url - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-generate-embed-url + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-generate-embed-url", + Type: "looker-generate-embed-url", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerGenerateEmbedUrl(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -85,23 +80,19 @@ func TestFailParseFromYamlLookerGenerateEmbedUrl(t *testing.T) { { desc: "Invalid field", in: ` - tools: - example_tool: - kind: looker-generate-embed-url - source: my-instance - description: some description - invalid_field: "should not be here" + kind: tools + name: example_tool + type: looker-generate-embed-url + source: my-instance + description: some description + invalid_field: "should not be here" `, err: "unknown field", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases.go b/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases.go index 96c80f5cdd3b..d0c37ff589c4 100644 --- a/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases.go +++ b/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases.go @@ -27,11 +27,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-connection-databases" +const resourceType string = "looker-get-connection-databases" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -149,7 +149,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -161,9 +161,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases_test.go b/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases_test.go index 284d4102bb74..6f137e85dc7e 100644 --- a/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases_test.go +++ b/internal/tools/looker/lookergetconnectiondatabases/lookergetconnectiondatabases_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetConnectionDatabases(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-connection-databases - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-connection-databases + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-connection-databases", + Type: "looker-get-connection-databases", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetConnectionDatabases(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetConnectionDatabases(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-connection-databases - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-connection-databases + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-connection-databases\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-connection-databases\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-connection-databases\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-connection-databases", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetconnections/lookergetconnections.go b/internal/tools/looker/lookergetconnections/lookergetconnections.go index f6875b3d3b4d..ccd384c5f7ef 100644 --- a/internal/tools/looker/lookergetconnections/lookergetconnections.go +++ b/internal/tools/looker/lookergetconnections/lookergetconnections.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-connections" +const resourceType string = "looker-get-connections" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -180,9 +180,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetconnections/lookergetconnections_test.go b/internal/tools/looker/lookergetconnections/lookergetconnections_test.go index b921a57e9434..0e7cc0377769 100644 --- a/internal/tools/looker/lookergetconnections/lookergetconnections_test.go +++ b/internal/tools/looker/lookergetconnections/lookergetconnections_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetConnections(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-connections - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-connections + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-connections", + Type: "looker-get-connections", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetConnections(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetConnections(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-connections - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-connections + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-connections\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-connections\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-connections\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-connections", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas.go b/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas.go index 472bf3166f7c..5ce3007d971b 100644 --- a/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas.go +++ b/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas.go @@ -27,11 +27,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-connection-schemas" +const resourceType string = "looker-get-connection-schemas" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -109,7 +109,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -155,7 +155,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -167,9 +167,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas_test.go b/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas_test.go index 1c2951102fd7..c0e720751748 100644 --- a/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas_test.go +++ b/internal/tools/looker/lookergetconnectionschemas/lookergetconnectionschemas_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetConnectionSchemas(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-connection-schemas - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-connection-schemas + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-connection-schemas", + Type: "looker-get-connection-schemas", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetConnectionSchemas(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetConnectionSchemas(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-connection-schemas - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-connection-schemas + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-connection-schemas\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-connection-schemas\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-connection-schemas\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-connection-schemas", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns.go b/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns.go index 1fdeadd1fda5..0b5f0e15c12c 100644 --- a/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns.go +++ b/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns.go @@ -8,7 +8,7 @@ // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// WITHOUT WARRANTIES OR CONDITIONS OF ANY, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package lookergetconnectiontablecolumns @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-connection-table-columns" +const resourceType string = "looker-get-connection-table-columns" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -112,7 +112,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -192,7 +192,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -204,9 +204,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns_test.go b/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns_test.go index 3242a31ffb07..c01a8ce8d17f 100644 --- a/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns_test.go +++ b/internal/tools/looker/lookergetconnectiontablecolumns/lookergetconnectiontablecolumns_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetConnectionTableColumns(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-connection-table-columns - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-connection-table-columns + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-connection-table-columns", + Type: "looker-get-connection-table-columns", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetConnectionTableColumns(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetConnectionTableColumns(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-connection-table-columns - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-connection-table-columns + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-connection-table-columns\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-connection-table-columns\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-connection-table-columns\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-connection-table-columns", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables.go b/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables.go index dfdbd120e462..141f5e5478dc 100644 --- a/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables.go +++ b/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-connection-tables" +const resourceType string = "looker-get-connection-tables" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -183,7 +183,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -195,9 +195,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables_test.go b/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables_test.go index 1b6ec50aa02f..0267accaf59c 100644 --- a/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables_test.go +++ b/internal/tools/looker/lookergetconnectiontables/lookergetconnectiontables_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetConnectionTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-connection-tables - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-connection-tables + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-connection-tables", + Type: "looker-get-connection-tables", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetConnectionTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetConnectionTables(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-connection-tables - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-connection-tables + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-connection-tables\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-connection-tables\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-connection-tables\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-connection-tables", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetdashboards/lookergetdashboards.go b/internal/tools/looker/lookergetdashboards/lookergetdashboards.go index 60b5e82503da..1fc574f10493 100644 --- a/internal/tools/looker/lookergetdashboards/lookergetdashboards.go +++ b/internal/tools/looker/lookergetdashboards/lookergetdashboards.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-dashboards" +const resourceType string = "looker-get-dashboards" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -117,7 +117,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -194,7 +194,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -206,9 +206,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetdashboards/lookergetdashboards_test.go b/internal/tools/looker/lookergetdashboards/lookergetdashboards_test.go index b3eba2af622b..83e2e8f9c58c 100644 --- a/internal/tools/looker/lookergetdashboards/lookergetdashboards_test.go +++ b/internal/tools/looker/lookergetdashboards/lookergetdashboards_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetDashboards(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-dashboards - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-dashboards + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-dashboards", + Type: "looker-get-dashboards", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetDashboards(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetDashboards(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-dashboards - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-dashboards + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-dashboards\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-dashboards\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-dashboards\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-dashboards", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetdimensions/lookergetdimensions.go b/internal/tools/looker/lookergetdimensions/lookergetdimensions.go index 1144a8c4208d..812dc41cb8dd 100644 --- a/internal/tools/looker/lookergetdimensions/lookergetdimensions.go +++ b/internal/tools/looker/lookergetdimensions/lookergetdimensions.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-dimensions" +const resourceType string = "looker-get-dimensions" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,9 +181,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetdimensions/lookergetdimensions_test.go b/internal/tools/looker/lookergetdimensions/lookergetdimensions_test.go index 53dba275334c..5d63e5d0748c 100644 --- a/internal/tools/looker/lookergetdimensions/lookergetdimensions_test.go +++ b/internal/tools/looker/lookergetdimensions/lookergetdimensions_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetDimensions(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-dimensions - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-dimensions + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-dimensions", + Type: "looker-get-dimensions", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetDimensions(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetDimensions(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-dimensions - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-dimensions + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-dimensions\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-dimensions\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-dimensions\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-dimensions", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetexplores/lookergetexplores.go b/internal/tools/looker/lookergetexplores/lookergetexplores.go index 39996152ecf9..99c7ad5caca2 100644 --- a/internal/tools/looker/lookergetexplores/lookergetexplores.go +++ b/internal/tools/looker/lookergetexplores/lookergetexplores.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-explores" +const resourceType string = "looker-get-explores" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -190,9 +190,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetexplores/lookergetexplores_test.go b/internal/tools/looker/lookergetexplores/lookergetexplores_test.go index 1c0b0d72b367..4e3aa5079582 100644 --- a/internal/tools/looker/lookergetexplores/lookergetexplores_test.go +++ b/internal/tools/looker/lookergetexplores/lookergetexplores_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetExplores(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-explores - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-explores + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-explores", + Type: "looker-get-explores", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetExplores(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetFilters(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-explores - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-explores + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-explores\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-explores\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-explores\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-explores", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetfilters/lookergetfilters.go b/internal/tools/looker/lookergetfilters/lookergetfilters.go index 880680bbdb39..8171d7c421a8 100644 --- a/internal/tools/looker/lookergetfilters/lookergetfilters.go +++ b/internal/tools/looker/lookergetfilters/lookergetfilters.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-filters" +const resourceType string = "looker-get-filters" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,9 +181,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetfilters/lookergetfilters_test.go b/internal/tools/looker/lookergetfilters/lookergetfilters_test.go index 0cec5dd0bbf2..76b3ab19db28 100644 --- a/internal/tools/looker/lookergetfilters/lookergetfilters_test.go +++ b/internal/tools/looker/lookergetfilters/lookergetfilters_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetFilters(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-filters - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-filters + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-filters", + Type: "looker-get-filters", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetFilters(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetFilters(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-filters - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-filters + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-filters\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-filters\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-filters\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-filters", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetlooks/lookergetlooks.go b/internal/tools/looker/lookergetlooks/lookergetlooks.go index 9a3a8a545679..bf934c441869 100644 --- a/internal/tools/looker/lookergetlooks/lookergetlooks.go +++ b/internal/tools/looker/lookergetlooks/lookergetlooks.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-looks" +const resourceType string = "looker-get-looks" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -117,7 +117,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -194,7 +194,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -206,9 +206,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetlooks/lookergetlooks_test.go b/internal/tools/looker/lookergetlooks/lookergetlooks_test.go index b6a4f23dd7e4..56320498ebda 100644 --- a/internal/tools/looker/lookergetlooks/lookergetlooks_test.go +++ b/internal/tools/looker/lookergetlooks/lookergetlooks_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetLooks(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-looks - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-looks + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-looks", + Type: "looker-get-looks", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetLooks(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetLooks(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-looks - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-looks + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-looks\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-looks\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-looks\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-looks", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetmeasures/lookergetmeasures.go b/internal/tools/looker/lookergetmeasures/lookergetmeasures.go index 9ca671841fb4..bba326945179 100644 --- a/internal/tools/looker/lookergetmeasures/lookergetmeasures.go +++ b/internal/tools/looker/lookergetmeasures/lookergetmeasures.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-measures" +const resourceType string = "looker-get-measures" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,9 +181,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetmeasures/lookergetmeasures_test.go b/internal/tools/looker/lookergetmeasures/lookergetmeasures_test.go index 7587b4cd3c85..cb29d86f85f1 100644 --- a/internal/tools/looker/lookergetmeasures/lookergetmeasures_test.go +++ b/internal/tools/looker/lookergetmeasures/lookergetmeasures_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetMeasures(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-measures - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-measures + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-measures", + Type: "looker-get-measures", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetMeasures(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetMeasures(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-measures - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-measures + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-measures\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-measures\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-measures\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-measures", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetmodels/lookergetmodels.go b/internal/tools/looker/lookergetmodels/lookergetmodels.go index 3ba6c30f91e8..a90d98635682 100644 --- a/internal/tools/looker/lookergetmodels/lookergetmodels.go +++ b/internal/tools/looker/lookergetmodels/lookergetmodels.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-models" +const resourceType string = "looker-get-models" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -109,7 +109,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -170,7 +170,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -182,9 +182,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetmodels/lookergetmodels_test.go b/internal/tools/looker/lookergetmodels/lookergetmodels_test.go index b28c02c31735..742d0045991f 100644 --- a/internal/tools/looker/lookergetmodels/lookergetmodels_test.go +++ b/internal/tools/looker/lookergetmodels/lookergetmodels_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetModels(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-models - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-models + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-models", + Type: "looker-get-models", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetModels(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetModels(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-models - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-models + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-models\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-models\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-models\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-models", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetparameters/lookergetparameters.go b/internal/tools/looker/lookergetparameters/lookergetparameters.go index 3dd0acb8331e..edacd0dc834f 100644 --- a/internal/tools/looker/lookergetparameters/lookergetparameters.go +++ b/internal/tools/looker/lookergetparameters/lookergetparameters.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-parameters" +const resourceType string = "looker-get-parameters" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -181,9 +181,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetparameters/lookergetparameters_test.go b/internal/tools/looker/lookergetparameters/lookergetparameters_test.go index 3c4679e8ecad..6c54db6e164d 100644 --- a/internal/tools/looker/lookergetparameters/lookergetparameters_test.go +++ b/internal/tools/looker/lookergetparameters/lookergetparameters_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetParameters(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-parameters - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-parameters + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-parameters", + Type: "looker-get-parameters", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetParameters(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetParameters(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-parameters - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-parameters + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-parameters\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-parameters\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-parameters\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-parameters", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetprojectfile/lookergetprojectfile.go b/internal/tools/looker/lookergetprojectfile/lookergetprojectfile.go index 1843860e75b5..d7eafebf1042 100644 --- a/internal/tools/looker/lookergetprojectfile/lookergetprojectfile.go +++ b/internal/tools/looker/lookergetprojectfile/lookergetprojectfile.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-project-file" +const resourceType string = "looker-get-project-file" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -166,7 +166,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -178,9 +178,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetprojectfile/lookergetprojectfile_test.go b/internal/tools/looker/lookergetprojectfile/lookergetprojectfile_test.go index cfd182c1d6c0..d3d5c9382ea4 100644 --- a/internal/tools/looker/lookergetprojectfile/lookergetprojectfile_test.go +++ b/internal/tools/looker/lookergetprojectfile/lookergetprojectfile_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetProjectFile(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-project-file - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-project-file + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-project-file", + Type: "looker-get-project-file", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetProjectFile(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,19 @@ func TestFailParseFromYamlLookerGetProjectFile(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-project-file - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-project-file + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-project-file\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-project-file\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-project-file\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-project-file", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles.go b/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles.go index d6e42ac451ef..832359dedf7c 100644 --- a/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles.go +++ b/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-project-files" +const resourceType string = "looker-get-project-files" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -109,7 +109,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -182,7 +182,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -194,9 +194,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles_test.go b/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles_test.go index 83a315b449e1..319b3f846196 100644 --- a/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles_test.go +++ b/internal/tools/looker/lookergetprojectfiles/lookergetprojectfiles_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetProjectFiles(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-project-files - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-project-files + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-project-files", + Type: "looker-get-project-files", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerGetProjectFiles(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerGetProjectFiles(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-project-files - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-project-files + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-project-files\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-project-files\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-project-files\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-project-files", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookergetprojects/lookergetprojects.go b/internal/tools/looker/lookergetprojects/lookergetprojects.go index fd7f0288da4f..17f0c438d1cd 100644 --- a/internal/tools/looker/lookergetprojects/lookergetprojects.go +++ b/internal/tools/looker/lookergetprojects/lookergetprojects.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-get-projects" +const resourceType string = "looker-get-projects" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -108,7 +108,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -159,7 +159,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -171,9 +171,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookergetprojects/lookergetprojects_test.go b/internal/tools/looker/lookergetprojects/lookergetprojects_test.go index 3a25be54d524..b3902574571e 100644 --- a/internal/tools/looker/lookergetprojects/lookergetprojects_test.go +++ b/internal/tools/looker/lookergetprojects/lookergetprojects_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerGetProjects(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-get-projects - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-get-projects + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-get-projects", + Type: "looker-get-projects", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerGetProjects(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +81,19 @@ func TestFailParseFromYamlLookerGetProjecProjects(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-get-projects - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-get-projects + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-get-projects\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-get-projects\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-projects\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-projects", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze.go b/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze.go index 1f3ef98d0506..2a11cf015567 100644 --- a/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze.go +++ b/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze.go @@ -34,11 +34,11 @@ import ( // ================================================================================================================= // START MCP SERVER CORE LOGIC // ================================================================================================================= -const kind string = "looker-health-analyze" +const resourceType string = "looker-health-analyze" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -69,8 +69,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -126,7 +126,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -210,7 +210,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -569,9 +569,13 @@ func (t *analyzeTool) explores(ctx context.Context, model, explore string) ([]ma // ================================================================================================================= func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze_test.go b/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze_test.go index 7d41a972e81f..52d0af8c89ac 100644 --- a/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze_test.go +++ b/internal/tools/looker/lookerhealthanalyze/lookerhealthanalyze_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerHealthAnalyze(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-health-analyze - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-health-analyze + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lha.Config{ Name: "example_tool", - Kind: "looker-health-analyze", + Type: "looker-health-analyze", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerHealthAnalyze(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -85,22 +80,18 @@ func TestFailParseFromYamlLookerHealthAnalyze(t *testing.T) { { desc: "Invalid field", in: ` - tools: - example_tool: - kind: looker-health-analyze - source: my-instance - invalid_field: true + kind: tools + name: example_tool + type: looker-health-analyze + source: my-instance + invalid_field: true `, - err: "unable to parse tool \"example_tool\" as kind \"looker-health-analyze\": [2:1] unknown field \"invalid_field\"", + err: "unable to parse tool \"example_tool\" as type \"looker-health-analyze\": [2:1] unknown field \"invalid_field\"", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerhealthpulse/lookerhealthpulse.go b/internal/tools/looker/lookerhealthpulse/lookerhealthpulse.go index 08556114d49f..b0df8b102211 100644 --- a/internal/tools/looker/lookerhealthpulse/lookerhealthpulse.go +++ b/internal/tools/looker/lookerhealthpulse/lookerhealthpulse.go @@ -34,11 +34,11 @@ import ( // ================================================================================================================= // START MCP SERVER CORE LOGIC // ================================================================================================================= -const kind string = "looker-health-pulse" +const resourceType string = "looker-health-pulse" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -69,8 +69,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -117,7 +117,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -174,7 +174,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -469,9 +469,13 @@ func (t *pulseTool) checkLegacyFeatures(ctx context.Context, source compatibleSo // ================================================================================================================= func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerhealthpulse/lookerhealthpulse_test.go b/internal/tools/looker/lookerhealthpulse/lookerhealthpulse_test.go index 12a7b69a7702..7ef3779bbdd9 100644 --- a/internal/tools/looker/lookerhealthpulse/lookerhealthpulse_test.go +++ b/internal/tools/looker/lookerhealthpulse/lookerhealthpulse_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerHealthPulse(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-health-pulse - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-health-pulse + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lhp.Config{ Name: "example_tool", - Kind: "looker-health-pulse", + Type: "looker-health-pulse", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerHealthPulse(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -85,22 +80,18 @@ func TestFailParseFromYamlLookerHealthPulse(t *testing.T) { { desc: "Invalid field", in: ` - tools: - example_tool: - kind: looker-health-pulse - source: my-instance - invalid_field: true + kind: tools + name: example_tool + type: looker-health-pulse + source: my-instance + invalid_field: true `, - err: "unable to parse tool \"example_tool\" as kind \"looker-health-pulse\": [2:1] unknown field \"invalid_field\"", + err: "unable to parse tool \"example_tool\" as type \"looker-health-pulse\": [2:1] unknown field \"invalid_field\"", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go b/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go index bb4e3c99678e..702808e86f3b 100644 --- a/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go +++ b/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go @@ -34,11 +34,11 @@ import ( // ================================================================================================================= // START MCP SERVER CORE LOGIC // ================================================================================================================= -const kind string = "looker-health-vacuum" +const resourceType string = "looker-health-vacuum" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -69,8 +69,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -126,7 +126,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -188,7 +188,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -473,9 +473,13 @@ func (t *vacuumTool) getUsedExploreFields(ctx context.Context, model, explore st // ================================================================================================================= func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum_test.go b/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum_test.go index 59fd2f21218b..7da00fc980f2 100644 --- a/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum_test.go +++ b/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerHealthVacuum(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-health-vacuum - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-health-vacuum + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lhv.Config{ Name: "example_tool", - Kind: "looker-health-vacuum", + Type: "looker-health-vacuum", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerHealthVacuum(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -85,22 +80,18 @@ func TestFailParseFromYamlLookerHealthVacuum(t *testing.T) { { desc: "Invalid field", in: ` - tools: - example_tool: - kind: looker-health-vacuum - source: my-instance - invalid_field: true + kind: tools + name: example_tool + type: looker-health-vacuum + source: my-instance + invalid_field: true `, - err: "unable to parse tool \"example_tool\" as kind \"looker-health-vacuum\": [2:1] unknown field \"invalid_field\"", + err: "unable to parse tool \"example_tool\" as type \"looker-health-vacuum\": [2:1] unknown field \"invalid_field\"", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookermakedashboard/lookermakedashboard.go b/internal/tools/looker/lookermakedashboard/lookermakedashboard.go index 13b0fc54b61a..0ca266009d0a 100644 --- a/internal/tools/looker/lookermakedashboard/lookermakedashboard.go +++ b/internal/tools/looker/lookermakedashboard/lookermakedashboard.go @@ -30,11 +30,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-make-dashboard" +const resourceType string = "looker-make-dashboard" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -117,7 +117,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -214,7 +214,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -226,9 +226,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookermakedashboard/lookermakedashboard_test.go b/internal/tools/looker/lookermakedashboard/lookermakedashboard_test.go index 2da79199ed2c..ef332cb1f66c 100644 --- a/internal/tools/looker/lookermakedashboard/lookermakedashboard_test.go +++ b/internal/tools/looker/lookermakedashboard/lookermakedashboard_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerMakeDashboard(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-make-dashboard - source: my-instance - description: some description - `, + kind: tools + name: example_tool + type: looker-make-dashboard + source: my-instance + description: some description + `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-make-dashboard", + Type: "looker-make-dashboard", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerMakeDashboard(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +81,19 @@ func TestFailParseFromYamlMakeDashboard(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-make-dashboard - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-make-dashboard + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-make-dashboard\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-make-dashboard\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-make-dashboard\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-make-dashboard", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookermakelook/lookermakelook.go b/internal/tools/looker/lookermakelook/lookermakelook.go index 43509cd5cc57..9784d1b953f8 100644 --- a/internal/tools/looker/lookermakelook/lookermakelook.go +++ b/internal/tools/looker/lookermakelook/lookermakelook.go @@ -31,11 +31,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-make-look" +const resourceType string = "looker-make-look" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -56,7 +56,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -124,7 +124,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -235,7 +235,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -247,9 +247,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookermakelook/lookermakelook_test.go b/internal/tools/looker/lookermakelook/lookermakelook_test.go index f6a3bd71f521..38e06a9aee67 100644 --- a/internal/tools/looker/lookermakelook/lookermakelook_test.go +++ b/internal/tools/looker/lookermakelook/lookermakelook_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerMakeLook(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-make-look - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-make-look + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-make-look", + Type: "looker-make-look", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerMakeLook(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +81,19 @@ func TestFailParseFromYamlLookerMakeLook(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-make-look - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-make-look + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-make-look\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-make-look\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-make-look\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-make-look", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerquery/lookerquery.go b/internal/tools/looker/lookerquery/lookerquery.go index 7120f46f02db..13dee7a81d8f 100644 --- a/internal/tools/looker/lookerquery/lookerquery.go +++ b/internal/tools/looker/lookerquery/lookerquery.go @@ -30,11 +30,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-query" +const resourceType string = "looker-query" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -162,7 +162,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -174,9 +174,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerquery/lookerquery_test.go b/internal/tools/looker/lookerquery/lookerquery_test.go index e204096e504e..1e30a96da463 100644 --- a/internal/tools/looker/lookerquery/lookerquery_test.go +++ b/internal/tools/looker/lookerquery/lookerquery_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-query - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-query + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-query", + Type: "looker-query", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,11 @@ func TestParseFromYamlLookerQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +81,19 @@ func TestFailParseFromYamlLookerQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-query - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-query + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-query\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-query\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-query\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-query", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerquerysql/lookerquerysql.go b/internal/tools/looker/lookerquerysql/lookerquerysql.go index b5873119288d..71eb14e27abe 100644 --- a/internal/tools/looker/lookerquerysql/lookerquerysql.go +++ b/internal/tools/looker/lookerquerysql/lookerquerysql.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-query-sql" +const resourceType string = "looker-query-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -109,7 +109,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -152,7 +152,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -164,9 +164,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerquerysql/lookerquerysql_test.go b/internal/tools/looker/lookerquerysql/lookerquerysql_test.go index bb8e25d7a42b..6a49f36bbeea 100644 --- a/internal/tools/looker/lookerquerysql/lookerquerysql_test.go +++ b/internal/tools/looker/lookerquerysql/lookerquerysql_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerQuerySql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-query-sql - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-query-sql + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-query-sql", + Type: "looker-query-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerQuerySql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerQuerySql(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-query-sql - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-query-sql + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-query-sql\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-query-sql\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-query-sql\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-query-sql", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerqueryurl/lookerqueryurl.go b/internal/tools/looker/lookerqueryurl/lookerqueryurl.go index 9cc5f4f50795..e47764eccf6a 100644 --- a/internal/tools/looker/lookerqueryurl/lookerqueryurl.go +++ b/internal/tools/looker/lookerqueryurl/lookerqueryurl.go @@ -29,11 +29,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-query-url" +const resourceType string = "looker-query-url" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -54,7 +54,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -116,7 +116,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -181,7 +181,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -193,9 +193,13 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerqueryurl/lookerqueryurl_test.go b/internal/tools/looker/lookerqueryurl/lookerqueryurl_test.go index 740e3aaa3e7f..e98838f91336 100644 --- a/internal/tools/looker/lookerqueryurl/lookerqueryurl_test.go +++ b/internal/tools/looker/lookerqueryurl/lookerqueryurl_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerQueryUrl(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-query-url - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-query-url + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-query-url", + Type: "looker-query-url", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerQueryUrl(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerQueryUrl(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-query-url - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-query-url + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-query-url\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-query-url\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-query-url\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-query-url", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerrundashboard/lookerrundashboard.go b/internal/tools/looker/lookerrundashboard/lookerrundashboard.go index 25081e5da7fd..8970c25671be 100644 --- a/internal/tools/looker/lookerrundashboard/lookerrundashboard.go +++ b/internal/tools/looker/lookerrundashboard/lookerrundashboard.go @@ -31,11 +31,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-run-dashboard" +const resourceType string = "looker-run-dashboard" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -56,7 +56,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -115,7 +115,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -279,9 +279,13 @@ func merge(channels ...<-chan map[string]any) <-chan map[string]any { } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerrundashboard/lookerrundashboard_test.go b/internal/tools/looker/lookerrundashboard/lookerrundashboard_test.go index 6726e045450b..20b55ce433b2 100644 --- a/internal/tools/looker/lookerrundashboard/lookerrundashboard_test.go +++ b/internal/tools/looker/lookerrundashboard/lookerrundashboard_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerRunDashboard(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-run-dashboard - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-run-dashboard + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-run-dashboard", + Type: "looker-run-dashboard", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerRunDashboard(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerRunDashboard(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-run-dashboard - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-run-dashboard + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-run-dashboard\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-run-dashboard\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-run-dashboard\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-run-dashboard", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerrunlook/lookerrunlook.go b/internal/tools/looker/lookerrunlook/lookerrunlook.go index c1c7123509a0..14513dfa6fb3 100644 --- a/internal/tools/looker/lookerrunlook/lookerrunlook.go +++ b/internal/tools/looker/lookerrunlook/lookerrunlook.go @@ -30,11 +30,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-run-look" +const resourceType string = "looker-run-look" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -55,7 +55,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -116,7 +116,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -191,7 +191,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -199,9 +199,13 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerrunlook/lookerrunlook_test.go b/internal/tools/looker/lookerrunlook/lookerrunlook_test.go index ac2dfbe99c94..ea4076b8435b 100644 --- a/internal/tools/looker/lookerrunlook/lookerrunlook_test.go +++ b/internal/tools/looker/lookerrunlook/lookerrunlook_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerRunLook(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-run-look - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-run-look + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-run-look", + Type: "looker-run-look", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerRunLook(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerRunLook(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-run-look - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-run-look + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-run-look\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-run-look\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-run-look\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-run-look", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile.go b/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile.go index 03701268aba8..40971944c79f 100644 --- a/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile.go +++ b/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile.go @@ -28,11 +28,11 @@ import ( v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4" ) -const kind string = "looker-update-project-file" +const resourceType string = "looker-update-project-file" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { } type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -112,7 +112,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -174,7 +174,7 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool { } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return false, err } @@ -182,9 +182,13 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo } func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return "", err } return source.GetAuthTokenHeaderName(), nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile_test.go b/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile_test.go index fef23faab72c..2d7064bbb284 100644 --- a/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile_test.go +++ b/internal/tools/looker/lookerupdateprojectfile/lookerupdateprojectfile_test.go @@ -18,7 +18,6 @@ import ( "strings" "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,16 +37,16 @@ func TestParseFromYamlLookerUpdateProjectFile(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: looker-update-project-file - source: my-instance - description: some description + kind: tools + name: example_tool + type: looker-update-project-file + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": lkr.Config{ Name: "example_tool", - Kind: "looker-update-project-file", + Type: "looker-update-project-file", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -57,15 +56,12 @@ func TestParseFromYamlLookerUpdateProjectFile(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -86,23 +82,20 @@ func TestFailParseFromYamlLookerUpdateProjectFile(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: looker-update-project-file - source: my-instance - method: GOT - description: some description + kind: tools + name: example_tool + type: looker-update-project-file + source: my-instance + method: GOT + description: some description `, - err: "unable to parse tool \"example_tool\" as kind \"looker-update-project-file\": [4:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n 3 | kind: looker-update-project-file\n> 4 | method: GOT\n ^\n 5 | source: my-instance", + err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-update-project-file\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-update-project-file", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql.go b/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql.go index f93097e8090b..da8c02398701 100644 --- a/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql.go +++ b/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mindsdb-execute-sql" +const resourceType string = "mindsdb-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -98,7 +98,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -139,3 +139,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql_test.go b/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql_test.go index 4c5f2b84cb37..db59ec7c5488 100644 --- a/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql_test.go +++ b/internal/tools/mindsdb/mindsdbexecutesql/mindsdbexecutesql_test.go @@ -17,7 +17,6 @@ package mindsdbexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mindsdb-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mindsdb-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mindsdbexecutesql.Config{ Name: "example_tool", - Kind: "mindsdb-execute-sql", + Type: "mindsdb-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mindsdb/mindsdbsql/mindsdbsql.go b/internal/tools/mindsdb/mindsdbsql/mindsdbsql.go index ee297865c64b..3fc78c6fcdff 100644 --- a/internal/tools/mindsdb/mindsdbsql/mindsdbsql.go +++ b/internal/tools/mindsdb/mindsdbsql/mindsdbsql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mindsdb-sql" +const resourceType string = "mindsdb-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -100,7 +100,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -151,3 +151,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mindsdb/mindsdbsql/mindsdbsql_test.go b/internal/tools/mindsdb/mindsdbsql/mindsdbsql_test.go index 3493717391ee..d20379719679 100644 --- a/internal/tools/mindsdb/mindsdbsql/mindsdbsql_test.go +++ b/internal/tools/mindsdb/mindsdbsql/mindsdbsql_test.go @@ -17,7 +17,6 @@ package mindsdbsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlmindsdbsql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mindsdb-sql - source: my-mindsdbsql-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: mindsdb-sql + source: my-mindsdbsql-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": mindsdbsql.Config{ Name: "example_tool", - Kind: "mindsdb-sql", + Type: "mindsdb-sql", Source: "my-mindsdbsql-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlmindsdbsql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -105,41 +101,41 @@ func TestParseFromYamlWithTemplateParamsmindsdbsql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mindsdb-sql - source: my-mindsdbsql-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: mindsdb-sql + source: my-mindsdbsql-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": mindsdbsql.Config{ Name: "example_tool", - Kind: "mindsdb-sql", + Type: "mindsdb-sql", Source: "my-mindsdbsql-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -159,15 +155,12 @@ func TestParseFromYamlWithTemplateParamsmindsdbsql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mongodb/mongodbaggregate/mongodbaggregate.go b/internal/tools/mongodb/mongodbaggregate/mongodbaggregate.go index 00bf5641aa4d..76210afa2aac 100644 --- a/internal/tools/mongodb/mongodbaggregate/mongodbaggregate.go +++ b/internal/tools/mongodb/mongodbaggregate/mongodbaggregate.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "mongodb-aggregate" +const resourceType string = "mongodb-aggregate" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -65,8 +65,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -103,7 +103,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,3 +147,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbaggregate/mongodbaggregate_test.go b/internal/tools/mongodb/mongodbaggregate/mongodbaggregate_test.go index 266ac5e98238..a9adf7f272c8 100644 --- a/internal/tools/mongodb/mongodbaggregate/mongodbaggregate_test.go +++ b/internal/tools/mongodb/mongodbaggregate/mongodbaggregate_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbaggregate" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,25 +39,25 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-aggregate - source: my-instance - description: some description - database: test_db - collection: test_coll - readOnly: true - pipelinePayload: | - [{ $match: { name: {{json .name}} }}] - pipelineParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-aggregate + source: my-instance + description: some description + database: test_db + collection: test_coll + readOnly: true + pipelinePayload: | + [{ $match: { name: {{json .name}} }}] + pipelineParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbaggregate.Config{ Name: "example_tool", - Kind: "mongodb-aggregate", + Type: "mongodb-aggregate", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -81,15 +80,12 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -110,25 +106,21 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-aggregate - source: my-instance - description: some description - collection: test_coll - pipelinePayload: | - [{ $match: { name : {{json .name}} }}] + kind: tools + name: example_tool + type: mongodb-aggregate + source: my-instance + description: some description + collection: test_coll + pipelinePayload: | + [{ $match: { name : {{json .name}} }}] `, - err: `unable to parse tool "example_tool" as kind "mongodb-aggregate"`, + err: `unable to parse tool "example_tool" as type "mongodb-aggregate"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany.go b/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany.go index 29a2a3349500..6b4bd9de27c2 100644 --- a/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany.go +++ b/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "mongodb-delete-many" +const resourceType string = "mongodb-delete-many" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -107,7 +107,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -151,3 +151,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany_test.go b/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany_test.go index e5861949cf94..af9ee4933e4d 100644 --- a/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany_test.go +++ b/internal/tools/mongodb/mongodbdeletemany/mongodbdeletemany_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbdeletemany" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,24 +39,24 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-delete-many - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-delete-many + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbdeletemany.Config{ Name: "example_tool", - Kind: "mongodb-delete-many", + Type: "mongodb-delete-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -79,15 +78,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -108,25 +103,21 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-delete-many - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} } + kind: tools + name: example_tool + type: mongodb-delete-many + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} } `, - err: `unable to parse tool "example_tool" as kind "mongodb-delete-many"`, + err: `unable to parse tool "example_tool" as type "mongodb-delete-many"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone.go b/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone.go index 2d761d83edea..a2506f8a4036 100644 --- a/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone.go +++ b/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "mongodb-delete-one" +const resourceType string = "mongodb-delete-one" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -107,7 +107,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -152,3 +152,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone_test.go b/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone_test.go index 4aa99da297b5..3f395c631593 100644 --- a/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone_test.go +++ b/internal/tools/mongodb/mongodbdeleteone/mongodbdeleteone_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbdeleteone" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,24 +39,24 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-delete-one - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-delete-one + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbdeleteone.Config{ Name: "example_tool", - Kind: "mongodb-delete-one", + Type: "mongodb-delete-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -79,15 +78,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -108,25 +103,21 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-delete-one - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} } + kind: tools + name: example_tool + type: mongodb-delete-one + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} } `, - err: `unable to parse tool "example_tool" as kind "mongodb-delete-one"`, + err: `unable to parse tool "example_tool" as type "mongodb-delete-one"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbfind/mongodbfind.go b/internal/tools/mongodb/mongodbfind/mongodbfind.go index 12ccd8463613..47083dba2c8a 100644 --- a/internal/tools/mongodb/mongodbfind/mongodbfind.go +++ b/internal/tools/mongodb/mongodbfind/mongodbfind.go @@ -30,11 +30,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "mongodb-find" +const resourceType string = "mongodb-find" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -53,7 +53,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -71,8 +71,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -158,7 +158,7 @@ func getOptions(ctx context.Context, sortParameters parameters.Parameters, proje } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -206,3 +206,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbfind/mongodbfind_test.go b/internal/tools/mongodb/mongodbfind/mongodbfind_test.go index 6b56d9c7c4f2..dcc25914148b 100644 --- a/internal/tools/mongodb/mongodbfind/mongodbfind_test.go +++ b/internal/tools/mongodb/mongodbfind/mongodbfind_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbfind" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,30 +39,30 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-find - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - projectPayload: | - { name: 1, age: 1 } - projectParams: [] - sortPayload: | - { timestamp: -1 } - sortParams: [] + kind: tools + name: example_tool + type: mongodb-find + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + projectPayload: | + { name: 1, age: 1 } + projectParams: [] + sortPayload: | + { timestamp: -1 } + sortParams: [] `, want: server.ToolConfigs{ "example_tool": mongodbfind.Config{ Name: "example_tool", - Kind: "mongodb-find", + Type: "mongodb-find", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -89,15 +88,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -118,25 +113,21 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-find - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} } + kind: tools + name: example_tool + type: mongodb-find + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} } `, - err: `unable to parse tool "example_tool" as kind "mongodb-find"`, + err: `unable to parse tool "example_tool" as type "mongodb-find"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbfindone/mongodbfindone.go b/internal/tools/mongodb/mongodbfindone/mongodbfindone.go index e9f1555c6697..2e185f088ee9 100644 --- a/internal/tools/mongodb/mongodbfindone/mongodbfindone.go +++ b/internal/tools/mongodb/mongodbfindone/mongodbfindone.go @@ -29,11 +29,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools" ) -const kind string = "mongodb-find-one" +const resourceType string = "mongodb-find-one" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -67,8 +67,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -169,3 +169,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbfindone/mongodbfindone_test.go b/internal/tools/mongodb/mongodbfindone/mongodbfindone_test.go index a8d5b9bfc05c..ce23e01e11b3 100644 --- a/internal/tools/mongodb/mongodbfindone/mongodbfindone_test.go +++ b/internal/tools/mongodb/mongodbfindone/mongodbfindone_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbfindone" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,27 +39,27 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-find-one - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - projectPayload: | - { name: 1, age: 1 } - projectParams: [] + kind: tools + name: example_tool + type: mongodb-find-one + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + projectPayload: | + { name: 1, age: 1 } + projectParams: [] `, want: server.ToolConfigs{ "example_tool": mongodbfindone.Config{ Name: "example_tool", - Kind: "mongodb-find-one", + Type: "mongodb-find-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -84,15 +83,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -113,25 +108,21 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-find-one - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} } + kind: tools + name: example_tool + type: mongodb-find-one + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} } `, - err: `unable to parse tool "example_tool" as kind "mongodb-find-one"`, + err: `unable to parse tool "example_tool" as type "mongodb-find-one"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go b/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go index 0dc11a230b67..d7e43de7f153 100644 --- a/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go +++ b/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany.go @@ -26,13 +26,13 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -const kind string = "mongodb-insert-many" +const resourceType string = "mongodb-insert-many" const paramDataKey = "data" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -101,7 +101,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -150,3 +150,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.PayloadParams +} diff --git a/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany_test.go b/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany_test.go index 19ac3ce0c115..e965e056d9c6 100644 --- a/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany_test.go +++ b/internal/tools/mongodb/mongodbinsertmany/mongodbinsertmany_test.go @@ -20,7 +20,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertmany" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,18 +38,18 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-insert-many - source: my-instance - description: some description - database: test_db - collection: test_coll + kind: tools + name: example_tool + type: mongodb-insert-many + source: my-instance + description: some description + database: test_db + collection: test_coll `, want: server.ToolConfigs{ "example_tool": mongodbinsertmany.Config{ Name: "example_tool", - Kind: "mongodb-insert-many", + Type: "mongodb-insert-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -63,19 +62,19 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "true canonical", in: ` - tools: - example_tool: - kind: mongodb-insert-many - source: my-instance - description: some description - database: test_db - collection: test_coll - canonical: true + kind: tools + name: example_tool + type: mongodb-insert-many + source: my-instance + description: some description + database: test_db + collection: test_coll + canonical: true `, want: server.ToolConfigs{ "example_tool": mongodbinsertmany.Config{ Name: "example_tool", - Kind: "mongodb-insert-many", + Type: "mongodb-insert-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -88,19 +87,19 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "false canonical", in: ` - tools: - example_tool: - kind: mongodb-insert-many - source: my-instance - description: some description - database: test_db - collection: test_coll - canonical: false + kind: tools + name: example_tool + type: mongodb-insert-many + source: my-instance + description: some description + database: test_db + collection: test_coll + canonical: false `, want: server.ToolConfigs{ "example_tool": mongodbinsertmany.Config{ Name: "example_tool", - Kind: "mongodb-insert-many", + Type: "mongodb-insert-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -113,15 +112,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -142,23 +137,19 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-insert-many - source: my-instance - description: some description - collection: test_coll + kind: tools + name: example_tool + type: mongodb-insert-many + source: my-instance + description: some description + collection: test_coll `, - err: `unable to parse tool "example_tool" as kind "mongodb-insert-many"`, + err: `unable to parse tool "example_tool" as type "mongodb-insert-many"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go b/internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go index a93589c053b9..bebe175d234d 100644 --- a/internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go +++ b/internal/tools/mongodb/mongodbinsertone/mongodbinsertone.go @@ -26,13 +26,13 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -const kind string = "mongodb-insert-one" +const resourceType string = "mongodb-insert-one" const dataParamsKey = "data" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -63,8 +63,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -102,7 +102,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -148,3 +148,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.PayloadParams +} diff --git a/internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go b/internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go index a61dde20b0bb..ace38f2d78a1 100644 --- a/internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go +++ b/internal/tools/mongodb/mongodbinsertone/mongodbinsertone_test.go @@ -20,7 +20,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbinsertone" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,18 +38,18 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-insert-one - source: my-instance - description: some description - database: test_db - collection: test_coll + kind: tools + name: example_tool + type: mongodb-insert-one + source: my-instance + description: some description + database: test_db + collection: test_coll `, want: server.ToolConfigs{ "example_tool": mongodbinsertone.Config{ Name: "example_tool", - Kind: "mongodb-insert-one", + Type: "mongodb-insert-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -63,19 +62,19 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "true canonical", in: ` - tools: - example_tool: - kind: mongodb-insert-one - source: my-instance - description: some description - database: test_db - collection: test_coll - canonical: true + kind: tools + name: example_tool + type: mongodb-insert-one + source: my-instance + description: some description + database: test_db + collection: test_coll + canonical: true `, want: server.ToolConfigs{ "example_tool": mongodbinsertone.Config{ Name: "example_tool", - Kind: "mongodb-insert-one", + Type: "mongodb-insert-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -88,19 +87,19 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "false canonical", in: ` - tools: - example_tool: - kind: mongodb-insert-one - source: my-instance - description: some description - database: test_db - collection: test_coll - canonical: false + kind: tools + name: example_tool + type: mongodb-insert-one + source: my-instance + description: some description + database: test_db + collection: test_coll + canonical: false `, want: server.ToolConfigs{ "example_tool": mongodbinsertone.Config{ Name: "example_tool", - Kind: "mongodb-insert-one", + Type: "mongodb-insert-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -113,15 +112,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -142,24 +137,20 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-insert-one - source: my-instance - description: some description - collection: test_coll - canonical: true + kind: tools + name: example_tool + type: mongodb-insert-one + source: my-instance + description: some description + collection: test_coll + canonical: true `, - err: `unable to parse tool "example_tool" as kind "mongodb-insert-one"`, + err: `unable to parse tool "example_tool" as type "mongodb-insert-one"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany.go b/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany.go index b80bc4972e4d..2d4def3fdc43 100644 --- a/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany.go +++ b/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany.go @@ -26,11 +26,11 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -const kind string = "mongodb-update-many" +const resourceType string = "mongodb-update-many" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -66,8 +66,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -158,3 +158,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany_test.go b/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany_test.go index b7353afe08f5..f3fcf468d560 100644 --- a/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany_test.go +++ b/internal/tools/mongodb/mongodbupdatemany/mongodbupdatemany_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbupdatemany" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,30 +39,30 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-update-many - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - updatePayload: | - { $set: { name: {{json .name}} } } - updateParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-update-many + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + updatePayload: | + { $set: { name: {{json .name}} } } + updateParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbupdatemany.Config{ Name: "example_tool", - Kind: "mongodb-update-many", + Type: "mongodb-update-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -96,31 +95,31 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "true canonical", in: ` - tools: - example_tool: - kind: mongodb-update-many - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - canonical: true - updatePayload: | - { $set: { name: {{json .name}} } } - updateParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-update-many + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + canonical: true + updatePayload: | + { $set: { name: {{json .name}} } } + updateParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbupdatemany.Config{ Name: "example_tool", - Kind: "mongodb-update-many", + Type: "mongodb-update-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -153,31 +152,31 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "false canonical", in: ` - tools: - example_tool: - kind: mongodb-update-many - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - canonical: false - updatePayload: | - { $set: { name: {{json .name}} } } - updateParams: - - name: name - type: string - description: small description + kind: tools + name: example_tool + type: mongodb-update-many + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + canonical: false + updatePayload: | + { $set: { name: {{json .name}} } } + updateParams: + - name: name + type: string + description: small description `, want: server.ToolConfigs{ "example_tool": mongodbupdatemany.Config{ Name: "example_tool", - Kind: "mongodb-update-many", + Type: "mongodb-update-many", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -210,15 +209,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -239,36 +234,32 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-update-many - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} } - filterParams: - - name: name - type: string - description: small description - canonical: true - updatePayload: | - { $set: { name: {{json .name}} } } - updateParams: - - name: data - type: string - description: the content in json + kind: tools + name: example_tool + type: mongodb-update-many + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} } + filterParams: + - name: name + type: string + description: small description + canonical: true + updatePayload: | + { $set: { name: {{json .name}} } } + updateParams: + - name: data + type: string + description: the content in json `, - err: `unable to parse tool "example_tool" as kind "mongodb-update-many"`, + err: `unable to parse tool "example_tool" as type "mongodb-update-many"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mongodb/mongodbupdateone/mongodbupdateone.go b/internal/tools/mongodb/mongodbupdateone/mongodbupdateone.go index d3236992e843..1addaf8d2914 100644 --- a/internal/tools/mongodb/mongodbupdateone/mongodbupdateone.go +++ b/internal/tools/mongodb/mongodbupdateone/mongodbupdateone.go @@ -26,11 +26,11 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -const kind string = "mongodb-update-one" +const resourceType string = "mongodb-update-one" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` AuthRequired []string `yaml:"authRequired" validate:"required"` Description string `yaml:"description" validate:"required"` @@ -67,8 +67,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -159,3 +159,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mongodb/mongodbupdateone/mongodbupdateone_test.go b/internal/tools/mongodb/mongodbupdateone/mongodbupdateone_test.go index b450892fb2d6..87202485f7b0 100644 --- a/internal/tools/mongodb/mongodbupdateone/mongodbupdateone_test.go +++ b/internal/tools/mongodb/mongodbupdateone/mongodbupdateone_test.go @@ -21,7 +21,6 @@ import ( "github.com/googleapis/genai-toolbox/internal/tools/mongodb/mongodbupdateone" "github.com/googleapis/genai-toolbox/internal/util/parameters" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -40,31 +39,31 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mongodb-update-one - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - updatePayload: | - { $set : { item: {{json .item}} } } - updateParams: - - name: item - type: string - description: small description - upsert: true + kind: tools + name: example_tool + type: mongodb-update-one + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + updatePayload: | + { $set : { item: {{json .item}} } } + updateParams: + - name: item + type: string + description: small description + upsert: true `, want: server.ToolConfigs{ "example_tool": mongodbupdateone.Config{ Name: "example_tool", - Kind: "mongodb-update-one", + Type: "mongodb-update-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -98,32 +97,32 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "false canonical", in: ` - tools: - example_tool: - kind: mongodb-update-one - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - updatePayload: | - { $set : { item: {{json .item}} } } - updateParams: - - name: item - type: string - description: small description - canonical: false - upsert: true + kind: tools + name: example_tool + type: mongodb-update-one + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + updatePayload: | + { $set : { item: {{json .item}} } } + updateParams: + - name: item + type: string + description: small description + canonical: false + upsert: true `, want: server.ToolConfigs{ "example_tool": mongodbupdateone.Config{ Name: "example_tool", - Kind: "mongodb-update-one", + Type: "mongodb-update-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -157,32 +156,32 @@ func TestParseFromYamlMongoQuery(t *testing.T) { { desc: "true canonical", in: ` - tools: - example_tool: - kind: mongodb-update-one - source: my-instance - description: some description - database: test_db - collection: test_coll - filterPayload: | - { name: {{json .name}} } - filterParams: - - name: name - type: string - description: small description - updatePayload: | - { $set : { item: {{json .item}} } } - updateParams: - - name: item - type: string - description: small description - canonical: true - upsert: true + kind: tools + name: example_tool + type: mongodb-update-one + source: my-instance + description: some description + database: test_db + collection: test_coll + filterPayload: | + { name: {{json .name}} } + filterParams: + - name: name + type: string + description: small description + updatePayload: | + { $set : { item: {{json .item}} } } + updateParams: + - name: item + type: string + description: small description + canonical: true + upsert: true `, want: server.ToolConfigs{ "example_tool": mongodbupdateone.Config{ Name: "example_tool", - Kind: "mongodb-update-one", + Type: "mongodb-update-one", Source: "my-instance", AuthRequired: []string{}, Database: "test_db", @@ -216,15 +215,11 @@ func TestParseFromYamlMongoQuery(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -245,24 +240,20 @@ func TestFailParseFromYamlMongoQuery(t *testing.T) { { desc: "Invalid method", in: ` - tools: - example_tool: - kind: mongodb-update-one - source: my-instance - description: some description - collection: test_coll - filterPayload: | - { name : {{json .name}} }`, - err: `unable to parse tool "example_tool" as kind "mongodb-update-one"`, + kind: tools + name: example_tool + type: mongodb-update-one + source: my-instance + description: some description + collection: test_coll + filterPayload: | + { name : {{json .name}} }`, + err: `unable to parse tool "example_tool" as type "mongodb-update-one"`, }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql.go b/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql.go index efa43cec030c..cdaa8df1e9ca 100644 --- a/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql.go +++ b/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mssql-execute-sql" +const resourceType string = "mssql-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -106,7 +106,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -141,3 +141,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql_test.go b/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql_test.go index 5042b5421516..560be13cade9 100644 --- a/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql_test.go +++ b/internal/tools/mssql/mssqlexecutesql/mssqlexecutesql_test.go @@ -17,7 +17,6 @@ package mssqlexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mssql-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mssql-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mssqlexecutesql.Config{ Name: "example_tool", - Kind: "mssql-execute-sql", + Type: "mssql-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mssql/mssqllisttables/mssqllisttables.go b/internal/tools/mssql/mssqllisttables/mssqllisttables.go index 82f987b9a55f..99a5e2d36e02 100644 --- a/internal/tools/mssql/mssqllisttables/mssqllisttables.go +++ b/internal/tools/mssql/mssqllisttables/mssqllisttables.go @@ -26,7 +26,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mssql-list-tables" +const resourceType string = "mssql-list-tables" const listTablesStatement = ` WITH table_info AS ( @@ -278,8 +278,8 @@ const listTablesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -298,7 +298,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -307,8 +307,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -340,7 +340,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -399,3 +399,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mssql/mssqllisttables/mssqllisttables_test.go b/internal/tools/mssql/mssqllisttables/mssqllisttables_test.go index 029a89a1caf9..1da6d18eae5b 100644 --- a/internal/tools/mssql/mssqllisttables/mssqllisttables_test.go +++ b/internal/tools/mssql/mssqllisttables/mssqllisttables_test.go @@ -17,7 +17,6 @@ package mssqllisttables_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlmssqlListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mssql-list-tables - source: my-mssql-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mssql-list-tables + source: my-mssql-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mssqllisttables.Config{ Name: "example_tool", - Kind: "mssql-list-tables", + Type: "mssql-list-tables", Source: "my-mssql-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlmssqlListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mssql/mssqlsql/mssqlsql.go b/internal/tools/mssql/mssqlsql/mssqlsql.go index d0ce09c9e86c..60c60550ee4a 100644 --- a/internal/tools/mssql/mssqlsql/mssqlsql.go +++ b/internal/tools/mssql/mssqlsql/mssqlsql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mssql-sql" +const resourceType string = "mssql-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -62,8 +62,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -95,7 +95,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -157,3 +157,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mssql/mssqlsql/mssqlsql_test.go b/internal/tools/mssql/mssqlsql/mssqlsql_test.go index 3fb9b44d8cac..043b97f0cebc 100644 --- a/internal/tools/mssql/mssqlsql/mssqlsql_test.go +++ b/internal/tools/mssql/mssqlsql/mssqlsql_test.go @@ -17,7 +17,6 @@ package mssqlsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlMssql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mssql-sql - source: my-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: mssql-sql + source: my-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": mssqlsql.Config{ Name: "example_tool", - Kind: "mssql-sql", + Type: "mssql-sql", Source: "my-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlMssql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -105,41 +101,41 @@ func TestParseFromYamlWithTemplateMssql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mssql-sql - source: my-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: mssql-sql + source: my-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": mssqlsql.Config{ Name: "example_tool", - Kind: "mssql-sql", + Type: "mssql-sql", Source: "my-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -159,15 +155,12 @@ func TestParseFromYamlWithTemplateMssql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql.go b/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql.go index f09bee748f1f..289c895ae60a 100644 --- a/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql.go +++ b/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-execute-sql" +const resourceType string = "mysql-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -106,7 +106,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -141,3 +141,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(_ tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql_test.go b/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql_test.go index 9044c2575d1d..43b4324728ca 100644 --- a/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql_test.go +++ b/internal/tools/mysql/mysqlexecutesql/mysqlexecutesql_test.go @@ -17,7 +17,6 @@ package mysqlexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqlexecutesql.Config{ Name: "example_tool", - Kind: "mysql-execute-sql", + Type: "mysql-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan.go b/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan.go index 07d4396cda81..9cf6c88d3bb7 100644 --- a/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan.go +++ b/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan.go @@ -29,11 +29,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-get-query-plan" +const resourceType string = "mysql-get-query-plan" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -52,7 +52,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -92,7 +92,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -108,7 +108,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) query := fmt.Sprintf("EXPLAIN FORMAT=JSON %s", sql) result, err := source.RunSQL(ctx, query, nil) @@ -166,3 +166,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(_ tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan_test.go b/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan_test.go index b06248dbaf30..43ed82aa354e 100644 --- a/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan_test.go +++ b/internal/tools/mysql/mysqlgetqueryplan/mysqlgetqueryplan_test.go @@ -17,7 +17,6 @@ package mysqlgetqueryplan_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlGetQueryPlan(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-get-query-plan - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-get-query-plan + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqlgetqueryplan.Config{ Name: "example_tool", - Kind: "mysql-get-query-plan", + Type: "mysql-get-query-plan", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlGetQueryPlan(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries.go b/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries.go index 1cc564752b93..32dfc8d735a5 100644 --- a/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries.go +++ b/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries.go @@ -29,7 +29,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-list-active-queries" +const resourceType string = "mysql-list-active-queries" const listActiveQueriesStatementMySQL = ` SELECT @@ -94,8 +94,8 @@ const listActiveQueriesStatementCloudSQLMySQL = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -114,7 +114,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -123,8 +123,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -136,7 +136,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible _, ok = rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", kind, cfg.Source) + return nil, fmt.Errorf("invalid source for %q tool: source %q not compatible", resourceType, cfg.Source) } allParameters := parameters.Parameters{ @@ -146,14 +146,14 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, allParameters, nil) var statement string - sourceKind := rawS.SourceKind() - switch sourceKind { - case mysql.SourceKind: + sourceType := rawS.SourceType() + switch sourceType { + case mysql.SourceType: statement = listActiveQueriesStatementMySQL - case cloudsqlmysql.SourceKind: + case cloudsqlmysql.SourceType: statement = listActiveQueriesStatementCloudSQLMySQL default: - return nil, fmt.Errorf("unsupported source kind: %s", cfg.Source) + return nil, fmt.Errorf("unsupported source type: %s", cfg.Source) } // finish tool setup t := Tool{ @@ -178,7 +178,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -199,7 +199,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, t.statement)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, t.statement)) return source.RunSQL(ctx, t.statement, []any{duration, duration, limit}) } @@ -234,3 +234,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries_test.go b/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries_test.go index cacc41c1edc1..5351981f38fb 100644 --- a/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries_test.go +++ b/internal/tools/mysql/mysqllistactivequeries/mysqllistactivequeries_test.go @@ -17,7 +17,6 @@ package mysqllistactivequeries_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-list-active-queries - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-list-active-queries + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqllistactivequeries.Config{ Name: "example_tool", - Kind: "mysql-list-active-queries", + Type: "mysql-list-active-queries", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation.go b/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation.go index adadd806d0ee..2ad5a232ebae 100644 --- a/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation.go +++ b/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation.go @@ -27,7 +27,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-list-table-fragmentation" +const resourceType string = "mysql-list-table-fragmentation" const listTableFragmentationStatement = ` SELECT @@ -52,8 +52,8 @@ const listTableFragmentationStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -72,7 +72,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -81,8 +81,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -115,7 +115,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -144,7 +144,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, listTableFragmentationStatement)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, listTableFragmentationStatement)) sliceParams := []any{table_schema, table_schema, table_name, table_name, data_free_threshold_bytes, limit} return source.RunSQL(ctx, listTableFragmentationStatement, sliceParams) } @@ -180,3 +180,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation_test.go b/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation_test.go index 401f672e72f2..07867ae8b166 100644 --- a/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation_test.go +++ b/internal/tools/mysql/mysqllisttablefragmentation/mysqllisttablefragmentation_test.go @@ -17,7 +17,6 @@ package mysqllisttablefragmentation_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-list-table-fragmentation - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-list-table-fragmentation + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqllisttablefragmentation.Config{ Name: "example_tool", - Kind: "mysql-list-table-fragmentation", + Type: "mysql-list-table-fragmentation", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqllisttables/mysqllisttables.go b/internal/tools/mysql/mysqllisttables/mysqllisttables.go index 608ee5b5249b..1bc1753564d6 100644 --- a/internal/tools/mysql/mysqllisttables/mysqllisttables.go +++ b/internal/tools/mysql/mysqllisttables/mysqllisttables.go @@ -26,7 +26,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-list-tables" +const resourceType string = "mysql-list-tables" const listTablesStatement = ` SELECT @@ -182,8 +182,8 @@ const listTablesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -202,7 +202,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -211,8 +211,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -245,7 +245,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -303,3 +303,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mysql/mysqllisttables/mysqllisttables_test.go b/internal/tools/mysql/mysqllisttables/mysqllisttables_test.go index c195e4f4e71b..5112d88ed9bf 100644 --- a/internal/tools/mysql/mysqllisttables/mysqllisttables_test.go +++ b/internal/tools/mysql/mysqllisttables/mysqllisttables_test.go @@ -17,7 +17,6 @@ package mysqllisttables_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlMySQLListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-list-tables - source: my-mysql-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-list-tables + source: my-mysql-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqllisttables.Config{ Name: "example_tool", - Kind: "mysql-list-tables", + Type: "mysql-list-tables", Source: "my-mysql-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlMySQLListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes.go b/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes.go index 025f0b4bdf02..8b5464df0dea 100644 --- a/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes.go +++ b/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes.go @@ -27,7 +27,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-list-tables-missing-unique-indexes" +const resourceType string = "mysql-list-tables-missing-unique-indexes" const listTablesMissingUniqueIndexesStatement = ` SELECT @@ -53,8 +53,8 @@ const listTablesMissingUniqueIndexesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -73,7 +73,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -82,8 +82,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -114,7 +114,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -135,7 +135,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, listTablesMissingUniqueIndexesStatement)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, listTablesMissingUniqueIndexesStatement)) return source.RunSQL(ctx, listTablesMissingUniqueIndexesStatement, []any{table_schema, table_schema, limit}) } @@ -170,3 +170,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes_test.go b/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes_test.go index 6ee9c873476d..3c1f0715cb79 100644 --- a/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes_test.go +++ b/internal/tools/mysql/mysqllisttablesmissinguniqueindexes/mysqllisttablesmissinguniqueindexes_test.go @@ -17,7 +17,6 @@ package mysqllisttablesmissinguniqueindexes_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-list-tables-missing-unique-indexes - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: mysql-list-tables-missing-unique-indexes + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": mysqllisttablesmissinguniqueindexes.Config{ Name: "example_tool", - Kind: "mysql-list-tables-missing-unique-indexes", + Type: "mysql-list-tables-missing-unique-indexes", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/mysql/mysqlsql/mysqlsql.go b/internal/tools/mysql/mysqlsql/mysqlsql.go index 27a3c5971677..3e84b49158e1 100644 --- a/internal/tools/mysql/mysqlsql/mysqlsql.go +++ b/internal/tools/mysql/mysqlsql/mysqlsql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "mysql-sql" +const resourceType string = "mysql-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -145,3 +145,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/mysql/mysqlsql/mysqlsql_test.go b/internal/tools/mysql/mysqlsql/mysqlsql_test.go index 5863477f0b97..d825720de00a 100644 --- a/internal/tools/mysql/mysqlsql/mysqlsql_test.go +++ b/internal/tools/mysql/mysqlsql/mysqlsql_test.go @@ -17,7 +17,6 @@ package mysqlsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlMySQL(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-sql - source: my-mysql-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: mysql-sql + source: my-mysql-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": mysqlsql.Config{ Name: "example_tool", - Kind: "mysql-sql", + Type: "mysql-sql", Source: "my-mysql-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlMySQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -105,41 +101,41 @@ func TestParseFromYamlWithTemplateParamsMySQL(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: mysql-sql - source: my-mysql-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: mysql-sql + source: my-mysql-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": mysqlsql.Config{ Name: "example_tool", - Kind: "mysql-sql", + Type: "mysql-sql", Source: "my-mysql-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -159,15 +155,12 @@ func TestParseFromYamlWithTemplateParamsMySQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/neo4j/neo4jcypher/neo4jcypher.go b/internal/tools/neo4j/neo4jcypher/neo4jcypher.go index b783df5cdee4..d431af349cb7 100644 --- a/internal/tools/neo4j/neo4jcypher/neo4jcypher.go +++ b/internal/tools/neo4j/neo4jcypher/neo4jcypher.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "neo4j-cypher" +const resourceType string = "neo4j-cypher" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -86,7 +86,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,3 +126,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/neo4j/neo4jcypher/neo4jcypher_test.go b/internal/tools/neo4j/neo4jcypher/neo4jcypher_test.go index 898583f96117..d20cb1822cc6 100644 --- a/internal/tools/neo4j/neo4jcypher/neo4jcypher_test.go +++ b/internal/tools/neo4j/neo4jcypher/neo4jcypher_test.go @@ -17,7 +17,6 @@ package neo4jcypher import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,25 +36,25 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: neo4j-cypher - source: my-neo4j-instance - description: some tool description - authRequired: - - my-google-auth-service - - other-auth-service - statement: | - MATCH (c:Country) WHERE c.name = $country RETURN c.id as id; - parameters: - - name: country - type: string - description: country parameter description + kind: tools + name: example_tool + type: neo4j-cypher + source: my-neo4j-instance + description: some tool description + authRequired: + - my-google-auth-service + - other-auth-service + statement: | + MATCH (c:Country) WHERE c.name = $country RETURN c.id as id; + parameters: + - name: country + type: string + description: country parameter description `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "neo4j-cypher", + Type: "neo4j-cypher", Source: "my-neo4j-instance", Description: "some tool description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -69,15 +68,12 @@ func TestParseFromYamlNeo4j(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go b/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go index 316423da4986..5a0ce23a8222 100644 --- a/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go +++ b/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "neo4j-execute-cypher" +const resourceType string = "neo4j-execute-cypher" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` ReadOnly bool `yaml:"readOnly"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -95,7 +95,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -149,3 +149,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher_test.go b/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher_test.go index a28729264771..d45a7ba3d4d2 100644 --- a/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher_test.go +++ b/internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher_test.go @@ -17,7 +17,6 @@ package neo4jexecutecypher import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -36,19 +35,19 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: neo4j-execute-cypher - source: my-neo4j-instance - description: some tool description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: neo4j-execute-cypher + source: my-neo4j-instance + description: some tool description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "neo4j-execute-cypher", + Type: "neo4j-execute-cypher", Source: "my-neo4j-instance", Description: "some tool description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -58,20 +57,20 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "readonly example", in: ` - tools: - example_tool: - kind: neo4j-execute-cypher - source: my-neo4j-instance - description: some tool description - readOnly: true - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: neo4j-execute-cypher + source: my-neo4j-instance + description: some tool description + readOnly: true + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "neo4j-execute-cypher", + Type: "neo4j-execute-cypher", Source: "my-neo4j-instance", ReadOnly: true, Description: "some tool description", @@ -82,15 +81,12 @@ func TestParseFromYamlNeo4j(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/neo4j/neo4jschema/neo4jschema.go b/internal/tools/neo4j/neo4jschema/neo4jschema.go index bb38122cee83..755b1a448a19 100644 --- a/internal/tools/neo4j/neo4jschema/neo4jschema.go +++ b/internal/tools/neo4j/neo4jschema/neo4jschema.go @@ -31,13 +31,13 @@ import ( "github.com/neo4j/neo4j-go-driver/v5/neo4j" ) -// kind defines the unique identifier for this tool. -const kind string = "neo4j-schema" +// type defines the unique identifier for this tool. +const resourceType string = "neo4j-schema" // init registers the tool with the application's tool registry when the package is initialized. func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -62,7 +62,7 @@ type compatibleSource interface { // These settings are typically read from a YAML file. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -72,9 +72,9 @@ type Config struct { // Statically verify that Config implements the tools.ToolConfig interface. var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of this tool configuration. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of this tool configuration. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize sets up the tool with its dependencies and returns a ready-to-use Tool instance. @@ -114,7 +114,7 @@ type Tool struct { // Invoke executes the tool's main logic: fetching the Neo4j schema. // It first checks the cache for a valid schema before extracting it from the database. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -701,3 +701,8 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +// This tool does not have parameters, so return an empty set. +func (t Tool) GetParameters() parameters.Parameters { + return parameters.Parameters{} +} diff --git a/internal/tools/neo4j/neo4jschema/neo4jschema_test.go b/internal/tools/neo4j/neo4jschema/neo4jschema_test.go index 6960dd7c5811..850e237245f6 100644 --- a/internal/tools/neo4j/neo4jschema/neo4jschema_test.go +++ b/internal/tools/neo4j/neo4jschema/neo4jschema_test.go @@ -18,7 +18,6 @@ package neo4jschema import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,19 +38,19 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "basic example with default cache expiration", in: ` - tools: - example_tool: - kind: neo4j-schema - source: my-neo4j-instance - description: some tool description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: neo4j-schema + source: my-neo4j-instance + description: some tool description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "neo4j-schema", + Type: "neo4j-schema", Source: "my-neo4j-instance", Description: "some tool description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -62,17 +61,17 @@ func TestParseFromYamlNeo4j(t *testing.T) { { desc: "cache expire minutes set explicitly", in: ` - tools: - example_tool: - kind: neo4j-schema - source: my-neo4j-instance - description: some tool description - cacheExpireMinutes: 30 + kind: tools + name: example_tool + type: neo4j-schema + source: my-neo4j-instance + description: some tool description + cacheExpireMinutes: 30 `, want: server.ToolConfigs{ "example_tool": Config{ Name: "example_tool", - Kind: "neo4j-schema", + Type: "neo4j-schema", Source: "my-neo4j-instance", Description: "some tool description", AuthRequired: []string{}, // Expect an empty slice, not nil. @@ -83,15 +82,12 @@ func TestParseFromYamlNeo4j(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err = yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql.go b/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql.go index a962bc030c9e..75045dc0c884 100644 --- a/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql.go +++ b/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "oceanbase-execute-sql" +const resourceType string = "oceanbase-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -41,7 +41,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T return actual, nil } -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { // Invoke executes the SQL statement provided in the parameters. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -138,3 +138,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql_test.go b/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql_test.go index 0653765d2acb..7b7f36e7a3e9 100644 --- a/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql_test.go +++ b/internal/tools/oceanbase/oceanbaseexecutesql/oceanbaseexecutesql_test.go @@ -17,7 +17,6 @@ package oceanbaseexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,19 +37,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: oceanbase-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: oceanbase-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": oceanbaseexecutesql.Config{ Name: "example_tool", - Kind: "oceanbase-execute-sql", + Type: "oceanbase-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -60,15 +59,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/oceanbase/oceanbasesql/oceanbasesql.go b/internal/tools/oceanbase/oceanbasesql/oceanbasesql.go index 0d9a0d944152..f9178fd9d1d4 100644 --- a/internal/tools/oceanbase/oceanbasesql/oceanbasesql.go +++ b/internal/tools/oceanbase/oceanbasesql/oceanbasesql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "oceanbase-sql" +const resourceType string = "oceanbase-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -41,7 +41,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T return actual, nil } -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -95,7 +95,7 @@ type Tool struct { // Invoke executes the SQL statement with the provided parameters. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -149,3 +149,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/oceanbase/oceanbasesql/oceanbasesql_test.go b/internal/tools/oceanbase/oceanbasesql/oceanbasesql_test.go index 0b1806dd8408..2df6c04ba1d0 100644 --- a/internal/tools/oceanbase/oceanbasesql/oceanbasesql_test.go +++ b/internal/tools/oceanbase/oceanbasesql/oceanbasesql_test.go @@ -17,7 +17,6 @@ package oceanbasesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,21 +38,21 @@ func TestParseFromYamlOceanBaseSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: oceanbase-sql - source: my-instance - description: some description - statement: select * from t where id = ? - parameters: - - name: id - type: string - description: id param + kind: tools + name: example_tool + type: oceanbase-sql + source: my-instance + description: some description + statement: select * from t where id = ? + parameters: + - name: id + type: string + description: id param `, want: server.ToolConfigs{ "example_tool": oceanbasesql.Config{ Name: "example_tool", - Kind: "oceanbase-sql", + Type: "oceanbase-sql", Source: "my-instance", Description: "some description", Statement: "select * from t where id = ?", @@ -67,15 +66,12 @@ func TestParseFromYamlOceanBaseSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/oracle/oracleexecutesql/oracleexecutesql.go b/internal/tools/oracle/oracleexecutesql/oracleexecutesql.go index c0d7fb637475..c67c60bd5835 100644 --- a/internal/tools/oracle/oracleexecutesql/oracleexecutesql.go +++ b/internal/tools/oracle/oracleexecutesql/oracleexecutesql.go @@ -15,11 +15,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "oracle-execute-sql" +const resourceType string = "oracle-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -38,7 +38,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -47,8 +47,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -78,7 +78,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -94,7 +94,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, "executing `%s` tool query: %s", kind, sqlParam) + logger.DebugContext(ctx, "executing `%s` tool query: %s", resourceType, sqlParam) return source.RunSQL(ctx, sqlParam, nil) } @@ -129,3 +129,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/oracle/oracleexecutesql/oracleexecutesql_test.go b/internal/tools/oracle/oracleexecutesql/oracleexecutesql_test.go index 834d3d69819f..1d416ca087bc 100644 --- a/internal/tools/oracle/oracleexecutesql/oracleexecutesql_test.go +++ b/internal/tools/oracle/oracleexecutesql/oracleexecutesql_test.go @@ -5,7 +5,6 @@ package oracleexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -25,18 +24,18 @@ func TestParseFromYamlOracleExecuteSql(t *testing.T) { { desc: "basic example with auth", in: ` - tools: - run_adhoc_query: - kind: oracle-execute-sql - source: my-oracle-instance - description: Executes arbitrary SQL statements like INSERT or UPDATE. - authRequired: - - my-google-auth-service + kind: tools + name: run_adhoc_query + type: oracle-execute-sql + source: my-oracle-instance + description: Executes arbitrary SQL statements like INSERT or UPDATE. + authRequired: + - my-google-auth-service `, want: server.ToolConfigs{ "run_adhoc_query": oracleexecutesql.Config{ Name: "run_adhoc_query", - Kind: "oracle-execute-sql", + Type: "oracle-execute-sql", Source: "my-oracle-instance", Description: "Executes arbitrary SQL statements like INSERT or UPDATE.", AuthRequired: []string{"my-google-auth-service"}, @@ -46,16 +45,16 @@ func TestParseFromYamlOracleExecuteSql(t *testing.T) { { desc: "example without authRequired", in: ` - tools: - run_simple_update: - kind: oracle-execute-sql - source: db-dev - description: Runs a simple update operation. + kind: tools + name: run_simple_update + type: oracle-execute-sql + source: db-dev + description: Runs a simple update operation. `, want: server.ToolConfigs{ "run_simple_update": oracleexecutesql.Config{ Name: "run_simple_update", - Kind: "oracle-execute-sql", + Type: "oracle-execute-sql", Source: "db-dev", Description: "Runs a simple update operation.", AuthRequired: []string{}, @@ -65,15 +64,12 @@ func TestParseFromYamlOracleExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + // Parse contents + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/oracle/oraclesql/oraclesql.go b/internal/tools/oracle/oraclesql/oraclesql.go index 949ed327f98b..1a8390bce68a 100644 --- a/internal/tools/oracle/oraclesql/oraclesql.go +++ b/internal/tools/oracle/oraclesql/oraclesql.go @@ -14,11 +14,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "oracle-sql" +const resourceType string = "oracle-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -37,7 +37,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -49,8 +49,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -82,7 +82,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -137,3 +137,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/oracle/oraclesql/oraclesql_test.go b/internal/tools/oracle/oraclesql/oraclesql_test.go index 2ba0a7321c75..190afc259459 100644 --- a/internal/tools/oracle/oraclesql/oraclesql_test.go +++ b/internal/tools/oracle/oraclesql/oraclesql_test.go @@ -4,7 +4,6 @@ package oraclesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -24,19 +23,19 @@ func TestParseFromYamlOracleSql(t *testing.T) { { desc: "basic example with statement and auth", in: ` - tools: - get_user_by_id: - kind: oracle-sql - source: my-oracle-instance - description: Retrieves user details by ID. - statement: "SELECT id, name, email FROM users WHERE id = :1" - authRequired: - - my-google-auth-service + kind: tools + name: get_user_by_id + type: oracle-sql + source: my-oracle-instance + description: Retrieves user details by ID. + statement: "SELECT id, name, email FROM users WHERE id = :1" + authRequired: + - my-google-auth-service `, want: server.ToolConfigs{ "get_user_by_id": oraclesql.Config{ Name: "get_user_by_id", - Kind: "oracle-sql", + Type: "oracle-sql", Source: "my-oracle-instance", Description: "Retrieves user details by ID.", Statement: "SELECT id, name, email FROM users WHERE id = :1", @@ -47,17 +46,17 @@ func TestParseFromYamlOracleSql(t *testing.T) { { desc: "example with parameters and template parameters", in: ` - tools: - get_orders: - kind: oracle-sql - source: db-prod - description: Gets orders for a customer with optional filtering. - statement: "SELECT * FROM ${SCHEMA}.ORDERS WHERE customer_id = :customer_id AND status = :status" + kind: tools + name: get_orders + type: oracle-sql + source: db-prod + description: Gets orders for a customer with optional filtering. + statement: "SELECT * FROM ${SCHEMA}.ORDERS WHERE customer_id = :customer_id AND status = :status" `, want: server.ToolConfigs{ "get_orders": oraclesql.Config{ Name: "get_orders", - Kind: "oracle-sql", + Type: "oracle-sql", Source: "db-prod", Description: "Gets orders for a customer with optional filtering.", Statement: "SELECT * FROM ${SCHEMA}.ORDERS WHERE customer_id = :customer_id AND status = :status", @@ -68,15 +67,12 @@ func TestParseFromYamlOracleSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + // Parse contents + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview.go b/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview.go index c2c89791c9de..541aee41e083 100644 --- a/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview.go +++ b/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-database-overview" +const resourceType string = "postgres-database-overview" const databaseOverviewStatement = ` SELECT @@ -43,8 +43,8 @@ const databaseOverviewStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -63,7 +63,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -72,8 +72,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -111,7 +111,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -153,3 +153,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview_test.go b/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview_test.go index 63ea550d2a2e..77c455733ad6 100644 --- a/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview_test.go +++ b/internal/tools/postgres/postgresdatabaseoverview/postgresdatabaseoverview_test.go @@ -17,7 +17,6 @@ package postgresdatabaseoverview_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresDatabaseOverview(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-database-overview - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-database-overview + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgresdatabaseoverview.Config{ Name: "example_tool", - Kind: "postgres-database-overview", + Type: "postgres-database-overview", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresDatabaseOverview(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-database-overview - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-database-overview + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgresdatabaseoverview.Config{ Name: "example_tool", - Kind: "postgres-database-overview", + Type: "postgres-database-overview", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresDatabaseOverview(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgresexecutesql/postgresexecutesql.go b/internal/tools/postgres/postgresexecutesql/postgresexecutesql.go index aec0851759b9..2b9bec3ad63b 100644 --- a/internal/tools/postgres/postgresexecutesql/postgresexecutesql.go +++ b/internal/tools/postgres/postgresexecutesql/postgresexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-execute-sql" +const resourceType string = "postgres-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -105,7 +105,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -141,3 +141,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/postgres/postgresexecutesql/postgresexecutesql_test.go b/internal/tools/postgres/postgresexecutesql/postgresexecutesql_test.go index 6351b54c6415..9d4c61e929f3 100644 --- a/internal/tools/postgres/postgresexecutesql/postgresexecutesql_test.go +++ b/internal/tools/postgres/postgresexecutesql/postgresexecutesql_test.go @@ -17,7 +17,6 @@ package postgresexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgresexecutesql.Config{ Name: "example_tool", - Kind: "postgres-execute-sql", + Type: "postgres-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality.go b/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality.go index a104ea28589e..754ba1577580 100644 --- a/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality.go +++ b/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-get-column-cardinality" +const resourceType string = "postgres-get-column-cardinality" const getColumnCardinality = ` SELECT @@ -48,8 +48,8 @@ const getColumnCardinality = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -68,7 +68,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -77,8 +77,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -123,7 +123,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -165,3 +165,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality_test.go b/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality_test.go index e1ea31fe593a..c9eef23c2648 100644 --- a/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality_test.go +++ b/internal/tools/postgres/postgresgetcolumncardinality/postgresgetcolumncardinality_test.go @@ -17,7 +17,6 @@ package postgresgetcolumncardinality_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresGetColumnCardinality(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-get-column-cardinality - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-get-column-cardinality + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgresgetcolumncardinality.Config{ Name: "example_tool", - Kind: "postgres-get-column-cardinality", + Type: "postgres-get-column-cardinality", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresGetColumnCardinality(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-get-column-cardinality - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-get-column-cardinality + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgresgetcolumncardinality.Config{ Name: "example_tool", - Kind: "postgres-get-column-cardinality", + Type: "postgres-get-column-cardinality", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresGetColumnCardinality(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries.go b/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries.go index 81cea0d42dea..f53b158e8dac 100644 --- a/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries.go +++ b/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-active-queries" +const resourceType string = "postgres-list-active-queries" const listActiveQueriesStatement = ` SELECT @@ -52,8 +52,8 @@ const listActiveQueriesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -72,7 +72,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -81,8 +81,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -119,7 +119,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -166,3 +166,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries_test.go b/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries_test.go index 96a5caeb0ee1..1cf079d0d8e3 100644 --- a/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries_test.go +++ b/internal/tools/postgres/postgreslistactivequeries/postgreslistactivequeries_test.go @@ -17,7 +17,6 @@ package postgreslistactivequeries_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-active-queries - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-active-queries + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistactivequeries.Config{ Name: "example_tool", - Kind: "postgres-list-active-queries", + Type: "postgres-list-active-queries", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-active-queries - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-active-queries + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistactivequeries.Config{ Name: "example_tool", - Kind: "postgres-list-active-queries", + Type: "postgres-list-active-queries", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions.go b/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions.go index 3cc764c46052..900c22a6e361 100644 --- a/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions.go +++ b/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-available-extensions" +const resourceType string = "postgres-list-available-extensions" const listAvailableExtensionsQuery = ` SELECT @@ -39,8 +39,8 @@ const listAvailableExtensionsQuery = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -59,7 +59,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -68,8 +68,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -85,6 +85,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) AuthRequired: cfg.AuthRequired, }, mcpManifest: mcpManifest, + Parameters: params, } return t, nil } @@ -96,10 +97,11 @@ type Tool struct { Config manifest tools.Manifest mcpManifest tools.McpManifest + Parameters parameters.Parameters } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -137,3 +139,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions_test.go b/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions_test.go index 8c26d59cdd24..2a45d2b502f4 100644 --- a/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions_test.go +++ b/internal/tools/postgres/postgreslistavailableextensions/postgreslistavailableextensions_test.go @@ -17,7 +17,6 @@ package postgreslistavailableextensions_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-available-extensions - source: my-pg-instance - description: "some description" - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-available-extensions + source: my-pg-instance + description: "some description" + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistavailableextensions.Config{ Name: "example_tool", - Kind: "postgres-list-available-extensions", + Type: "postgres-list-available-extensions", Source: "my-pg-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example without authRequired", in: ` - tools: - example_tool: - kind: postgres-list-available-extensions - source: my-pg-instance - description: "some description" + kind: tools + name: example_tool + type: postgres-list-available-extensions + source: my-pg-instance + description: "some description" `, want: server.ToolConfigs{ "example_tool": postgreslistavailableextensions.Config{ Name: "example_tool", - Kind: "postgres-list-available-extensions", + Type: "postgres-list-available-extensions", Source: "my-pg-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgres(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats.go b/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats.go index b6c3e987c1c5..8bb221d7377f 100644 --- a/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats.go +++ b/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-database-stats" +const resourceType string = "postgres-list-database-stats" // SQL query to list database statistics const listDatabaseStats = ` @@ -96,8 +96,8 @@ const listDatabaseStats = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -116,7 +116,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -125,8 +125,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -188,7 +188,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -235,3 +235,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats_test.go b/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats_test.go index 760370f6304e..d90211e9e405 100644 --- a/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats_test.go +++ b/internal/tools/postgres/postgreslistdatabasestats/postgreslistdatabasestats_test.go @@ -17,7 +17,6 @@ package postgreslistdatabasestats_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListDatabaseStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-database-stats - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-database-stats + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistdatabasestats.Config{ Name: "example_tool", - Kind: "postgres-list-database-stats", + Type: "postgres-list-database-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListDatabaseStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-database-stats - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-database-stats + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistdatabasestats.Config{ Name: "example_tool", - Kind: "postgres-list-database-stats", + Type: "postgres-list-database-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListDatabaseStats(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistindexes/postgreslistindexes.go b/internal/tools/postgres/postgreslistindexes/postgreslistindexes.go index ac5a9b1d4047..4f4bf16b1e9b 100644 --- a/internal/tools/postgres/postgreslistindexes/postgreslistindexes.go +++ b/internal/tools/postgres/postgreslistindexes/postgreslistindexes.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-indexes" +const resourceType string = "postgres-list-indexes" const listIndexesStatement = ` WITH IndexDetails AS ( @@ -75,8 +75,8 @@ const listIndexesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -95,7 +95,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -104,8 +104,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -150,7 +150,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -193,3 +193,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistindexes/postgreslistindexes_test.go b/internal/tools/postgres/postgreslistindexes/postgreslistindexes_test.go index c5aaacfab7e5..7c0da6e6a177 100644 --- a/internal/tools/postgres/postgreslistindexes/postgreslistindexes_test.go +++ b/internal/tools/postgres/postgreslistindexes/postgreslistindexes_test.go @@ -17,7 +17,6 @@ package postgreslistindexes_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListIndexes(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-indexes - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-indexes + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistindexes.Config{ Name: "example_tool", - Kind: "postgres-list-indexes", + Type: "postgres-list-indexes", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListIndexes(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-indexes - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-indexes + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistindexes.Config{ Name: "example_tool", - Kind: "postgres-list-indexes", + Type: "postgres-list-indexes", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresListIndexes(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions.go b/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions.go index f9e577332952..57c891409515 100644 --- a/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions.go +++ b/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-installed-extensions" +const resourceType string = "postgres-list-installed-extensions" const listAvailableExtensionsQuery = ` SELECT @@ -50,8 +50,8 @@ const listAvailableExtensionsQuery = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -70,7 +70,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -79,8 +79,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -110,7 +110,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -148,3 +148,8 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +// This tool does not have parameters, so return an empty set. +func (t Tool) GetParameters() parameters.Parameters { + return parameters.Parameters{} +} diff --git a/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions_test.go b/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions_test.go index 8fb6b1e2a3ef..5ca5dbe3c06f 100644 --- a/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions_test.go +++ b/internal/tools/postgres/postgreslistinstalledextensions/postgreslistinstalledextensions_test.go @@ -17,7 +17,6 @@ package postgreslistinstalledextensions_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-installed-extensions - source: my-pg-instance - description: "some description" - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-installed-extensions + source: my-pg-instance + description: "some description" + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistinstalledextensions.Config{ Name: "example_tool", - Kind: "postgres-list-installed-extensions", + Type: "postgres-list-installed-extensions", Source: "my-pg-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example without authRequired", in: ` - tools: - example_tool: - kind: postgres-list-installed-extensions - source: my-pg-instance - description: "some description" + kind: tools + name: example_tool + type: postgres-list-installed-extensions + source: my-pg-instance + description: "some description" `, want: server.ToolConfigs{ "example_tool": postgreslistinstalledextensions.Config{ Name: "example_tool", - Kind: "postgres-list-installed-extensions", + Type: "postgres-list-installed-extensions", Source: "my-pg-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgres(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistlocks/postgreslistlocks.go b/internal/tools/postgres/postgreslistlocks/postgreslistlocks.go index b7cd44054c89..12e2cde58891 100644 --- a/internal/tools/postgres/postgreslistlocks/postgreslistlocks.go +++ b/internal/tools/postgres/postgreslistlocks/postgreslistlocks.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-locks" +const resourceType string = "postgres-list-locks" const listLocks = ` SELECT @@ -50,8 +50,8 @@ const listLocks = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -70,7 +70,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -79,8 +79,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -121,7 +121,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -164,3 +164,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistlocks/postgreslistlocks_test.go b/internal/tools/postgres/postgreslistlocks/postgreslistlocks_test.go index 1615e4870b1f..d34352e484e1 100644 --- a/internal/tools/postgres/postgreslistlocks/postgreslistlocks_test.go +++ b/internal/tools/postgres/postgreslistlocks/postgreslistlocks_test.go @@ -17,7 +17,6 @@ package postgreslistlocks_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListLocks(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-locks - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-locks + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistlocks.Config{ Name: "example_tool", - Kind: "postgres-list-locks", + Type: "postgres-list-locks", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListLocks(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-locks - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-locks + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistlocks.Config{ Name: "example_tool", - Kind: "postgres-list-locks", + Type: "postgres-list-locks", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresListLocks(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings.go b/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings.go index 707c5f299b64..83bdf890294a 100644 --- a/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings.go +++ b/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-pg-settings" +const resourceType string = "postgres-list-pg-settings" const listPgSettingsStatement = ` SELECT @@ -48,8 +48,8 @@ const listPgSettingsStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -68,7 +68,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -77,8 +77,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -116,7 +116,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -161,3 +161,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings_test.go b/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings_test.go index a2aa9fe78b93..eb98a8e370e7 100644 --- a/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings_test.go +++ b/internal/tools/postgres/postgreslistpgsettings/postgreslistpgsettings_test.go @@ -17,7 +17,6 @@ package postgreslistpgsettings_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgreslistPgSettings(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-pg-settings - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-pg-settings + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistpgsettings.Config{ Name: "example_tool", - Kind: "postgres-list-pg-settings", + Type: "postgres-list-pg-settings", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgreslistPgSettings(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-pg-settings - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-pg-settings + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistpgsettings.Config{ Name: "example_tool", - Kind: "postgres-list-pg-settings", + Type: "postgres-list-pg-settings", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgreslistPgSettings(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables.go b/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables.go index b9d57c44e7ae..f2362dfd6e9a 100644 --- a/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables.go +++ b/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-publication-tables" +const resourceType string = "postgres-list-publication-tables" const listPublicationTablesStatement = ` WITH @@ -59,8 +59,8 @@ const listPublicationTablesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -79,7 +79,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -88,8 +88,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -129,7 +129,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -175,3 +175,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables_test.go b/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables_test.go index 211567c4a84e..96e4db1b9577 100644 --- a/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables_test.go +++ b/internal/tools/postgres/postgreslistpublicationtables/postgreslistpublicationtables_test.go @@ -17,7 +17,6 @@ package postgreslistpublicationtables_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListPublicationTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-publication-tables - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-publication-tables + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistpublicationtables.Config{ Name: "example_tool", - Kind: "postgres-list-publication-tables", + Type: "postgres-list-publication-tables", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListPublicationTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-publication-tables - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-publication-tables + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistpublicationtables.Config{ Name: "example_tool", - Kind: "postgres-list-publication-tables", + Type: "postgres-list-publication-tables", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListPublicationTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats.go b/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats.go index d07dd4001eae..1aa68becb8d1 100644 --- a/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats.go +++ b/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-query-stats" +const resourceType string = "postgres-list-query-stats" const listQueryStats = ` SELECT @@ -49,8 +49,8 @@ const listQueryStats = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -69,7 +69,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -78,8 +78,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -123,7 +123,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -164,3 +164,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats_test.go b/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats_test.go index c8408aa95240..694a780d80a8 100644 --- a/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats_test.go +++ b/internal/tools/postgres/postgreslistquerystats/postgreslistquerystats_test.go @@ -17,7 +17,6 @@ package postgreslistquerystats_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListQueryStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-query-stats - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-query-stats + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistquerystats.Config{ Name: "example_tool", - Kind: "postgres-list-query-stats", + Type: "postgres-list-query-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListQueryStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-query-stats - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-query-stats + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistquerystats.Config{ Name: "example_tool", - Kind: "postgres-list-query-stats", + Type: "postgres-list-query-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListQueryStats(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistroles/postgreslistroles.go b/internal/tools/postgres/postgreslistroles/postgreslistroles.go index b180e0451c6b..b1b814b35211 100644 --- a/internal/tools/postgres/postgreslistroles/postgreslistroles.go +++ b/internal/tools/postgres/postgreslistroles/postgreslistroles.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-roles" +const resourceType string = "postgres-list-roles" const listRolesStatement = ` WITH RoleDetails AS ( @@ -71,8 +71,8 @@ const listRolesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -91,7 +91,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -100,8 +100,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -144,7 +144,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -186,3 +186,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistroles/postgreslistroles_test.go b/internal/tools/postgres/postgreslistroles/postgreslistroles_test.go index cf4249f6ff54..1d3c89f05691 100644 --- a/internal/tools/postgres/postgreslistroles/postgreslistroles_test.go +++ b/internal/tools/postgres/postgreslistroles/postgreslistroles_test.go @@ -17,7 +17,6 @@ package postgreslistroles_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListRoles(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-roles - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-roles + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistroles.Config{ Name: "example_tool", - Kind: "postgres-list-roles", + Type: "postgres-list-roles", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListRoles(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-roles - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-roles + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistroles.Config{ Name: "example_tool", - Kind: "postgres-list-roles", + Type: "postgres-list-roles", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListRoles(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistschemas/postgreslistschemas.go b/internal/tools/postgres/postgreslistschemas/postgreslistschemas.go index d97976a7e3e3..8fae3cc84488 100644 --- a/internal/tools/postgres/postgreslistschemas/postgreslistschemas.go +++ b/internal/tools/postgres/postgreslistschemas/postgreslistschemas.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-schemas" +const resourceType string = "postgres-list-schemas" const listSchemasStatement = ` WITH @@ -83,8 +83,8 @@ const listSchemasStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -103,7 +103,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -112,8 +112,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -152,7 +152,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -198,3 +198,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistschemas/postgreslistschemas_test.go b/internal/tools/postgres/postgreslistschemas/postgreslistschemas_test.go index a416d584bd49..62332b7e7dfd 100644 --- a/internal/tools/postgres/postgreslistschemas/postgreslistschemas_test.go +++ b/internal/tools/postgres/postgreslistschemas/postgreslistschemas_test.go @@ -17,7 +17,6 @@ package postgreslistschemas_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgreslistSchemas(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-schemas - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-schemas + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistschemas.Config{ Name: "example_tool", - Kind: "postgres-list-schemas", + Type: "postgres-list-schemas", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgreslistSchemas(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-schemas - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-schemas + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistschemas.Config{ Name: "example_tool", - Kind: "postgres-list-schemas", + Type: "postgres-list-schemas", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgreslistSchemas(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistsequences/postgreslistsequences.go b/internal/tools/postgres/postgreslistsequences/postgreslistsequences.go index fb55b9208c57..616d341e51cb 100644 --- a/internal/tools/postgres/postgreslistsequences/postgreslistsequences.go +++ b/internal/tools/postgres/postgreslistsequences/postgreslistsequences.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-sequences" +const resourceType string = "postgres-list-sequences" const listSequencesStatement = ` SELECT @@ -49,8 +49,8 @@ const listSequencesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -69,7 +69,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -78,8 +78,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -122,7 +122,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -165,3 +165,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistsequences/postgreslistsequences_test.go b/internal/tools/postgres/postgreslistsequences/postgreslistsequences_test.go index 566da0ef7b10..5491eec275ef 100644 --- a/internal/tools/postgres/postgreslistsequences/postgreslistsequences_test.go +++ b/internal/tools/postgres/postgreslistsequences/postgreslistsequences_test.go @@ -17,7 +17,6 @@ package postgreslistsequences_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListSequences(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-sequences - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-sequences + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistsequences.Config{ Name: "example_tool", - Kind: "postgres-list-sequences", + Type: "postgres-list-sequences", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListSequences(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-sequences - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-sequences + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistsequences.Config{ Name: "example_tool", - Kind: "postgres-list-sequences", + Type: "postgres-list-sequences", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListSequences(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure.go b/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure.go index 54d32ade0c75..713826ab3a6f 100644 --- a/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure.go +++ b/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure.go @@ -29,7 +29,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-stored-procedure" +const resourceType string = "postgres-list-stored-procedure" const listStoredProcedure = ` SELECT @@ -53,8 +53,8 @@ const listStoredProcedure = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -75,11 +75,11 @@ var _ compatibleSource = &alloydbpg.Source{} var _ compatibleSource = &cloudsqlpg.Source{} var _ compatibleSource = &postgres.Source{} -var compatibleSources = [...]string{alloydbpg.SourceKind, cloudsqlpg.SourceKind, postgres.SourceKind} +var compatibleSources = [...]string{alloydbpg.SourceType, cloudsqlpg.SourceType, postgres.SourceType} type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -88,8 +88,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -102,7 +102,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // verify the source is compatible s, ok := rawS.(compatibleSource) if !ok { - return nil, fmt.Errorf("invalid source for %q tool: source kind must be one of %q", kind, compatibleSources) + return nil, fmt.Errorf("invalid source for %q tool: source type must be one of %q", resourceType, compatibleSources) } allParameters := parameters.Parameters{ @@ -120,11 +120,9 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) // finish tool setup return Tool{ - name: cfg.Name, - kind: cfg.Kind, - authRequired: cfg.AuthRequired, - allParams: allParameters, - pool: s.PostgresPool(), + Config: cfg, + allParams: allParameters, + pool: s.PostgresPool(), manifest: tools.Manifest{ Description: cfg.Description, Parameters: paramManifest, @@ -139,13 +137,10 @@ var _ tools.Tool = Tool{} type Tool struct { Config - name string `yaml:"name"` - kind string `yaml:"kind"` - authRequired []string `yaml:"authRequired"` - allParams parameters.Parameters `yaml:"allParams"` - pool *pgxpool.Pool - manifest tools.Manifest - mcpManifest tools.McpManifest + allParams parameters.Parameters `yaml:"allParams"` + pool *pgxpool.Pool + manifest tools.Manifest + mcpManifest tools.McpManifest } func (t Tool) ToConfig() tools.ToolConfig { @@ -202,7 +197,7 @@ func (t Tool) McpManifest() tools.McpManifest { } func (t Tool) Authorized(verifiedAuthServices []string) bool { - return tools.IsAuthorized(t.authRequired, verifiedAuthServices) + return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices) } func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) { @@ -212,3 +207,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure_test.go b/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure_test.go index 0ded95f2d543..63593bd0eca5 100644 --- a/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure_test.go +++ b/internal/tools/postgres/postgresliststoredprocedure/postgresliststoredprocedure_test.go @@ -17,7 +17,6 @@ package postgresliststoredprocedure_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListStoredProcedure(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-stored-procedure - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-stored-procedure + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgresliststoredprocedure.Config{ Name: "example_tool", - Kind: "postgres-list-stored-procedure", + Type: "postgres-list-stored-procedure", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListStoredProcedure(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-stored-procedure - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-stored-procedure + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgresliststoredprocedure.Config{ Name: "example_tool", - Kind: "postgres-list-stored-procedure", + Type: "postgres-list-stored-procedure", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListStoredProcedure(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslisttables/postgreslisttables.go b/internal/tools/postgres/postgreslisttables/postgreslisttables.go index 3f10551edd8c..64a62d2fb260 100644 --- a/internal/tools/postgres/postgreslisttables/postgreslisttables.go +++ b/internal/tools/postgres/postgreslisttables/postgreslisttables.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-tables" +const resourceType string = "postgres-list-tables" const listTablesStatement = ` WITH desired_relkinds AS ( @@ -107,8 +107,8 @@ const listTablesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -127,7 +127,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -136,8 +136,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -169,7 +169,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -226,3 +226,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/postgres/postgreslisttables/postgreslisttables_test.go b/internal/tools/postgres/postgreslisttables/postgreslisttables_test.go index ded7f9e4cb97..fdb66825c97b 100644 --- a/internal/tools/postgres/postgreslisttables/postgreslisttables_test.go +++ b/internal/tools/postgres/postgreslisttables/postgreslisttables_test.go @@ -17,7 +17,6 @@ package postgreslisttables_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-tables - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-tables + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslisttables.Config{ Name: "example_tool", - Kind: "postgres-list-tables", + Type: "postgres-list-tables", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlPostgresListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces.go b/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces.go index 51d7b61f45ca..e1e3b2e7eac0 100644 --- a/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces.go +++ b/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-tablespaces" +const resourceType string = "postgres-list-tablespaces" const listTableSpacesStatement = ` WITH @@ -55,8 +55,8 @@ const listTableSpacesStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -75,7 +75,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -84,8 +84,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -127,7 +127,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -173,3 +173,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces_test.go b/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces_test.go index 0d28d5abf31f..88e134221a2e 100644 --- a/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces_test.go +++ b/internal/tools/postgres/postgreslisttablespaces/postgreslisttablespaces_test.go @@ -17,7 +17,6 @@ package postgreslisttablespaces_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListTablespaces(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-tablespaces - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-tablespaces + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslisttablespaces.Config{ Name: "example_tool", - Kind: "postgres-list-tablespaces", + Type: "postgres-list-tablespaces", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListTablespaces(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-tablespaces - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-tablespaces + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslisttablespaces.Config{ Name: "example_tool", - Kind: "postgres-list-tablespaces", + Type: "postgres-list-tablespaces", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresListTablespaces(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats.go b/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats.go index c4f8b34729e2..eca7e495b0bd 100644 --- a/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats.go +++ b/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-table-stats" +const resourceType string = "postgres-list-table-stats" const listTableStats = ` WITH table_stats AS ( @@ -76,8 +76,8 @@ const listTableStats = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -96,7 +96,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -105,8 +105,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -161,7 +161,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -204,3 +204,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats_test.go b/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats_test.go index cfaac3eda53c..c0c71c492475 100644 --- a/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats_test.go +++ b/internal/tools/postgres/postgreslisttablestats/postgreslisttablestats_test.go @@ -17,7 +17,6 @@ package postgreslisttablestats_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListTableStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-table-stats - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-table-stats + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslisttablestats.Config{ Name: "example_tool", - Kind: "postgres-list-table-stats", + Type: "postgres-list-table-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListTableStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-table-stats - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-table-stats + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslisttablestats.Config{ Name: "example_tool", - Kind: "postgres-list-table-stats", + Type: "postgres-list-table-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresListTableStats(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers.go b/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers.go index d92261ea9faa..5071bb7035d1 100644 --- a/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers.go +++ b/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-triggers" +const resourceType string = "postgres-list-triggers" const listTriggersStatement = ` WITH @@ -75,8 +75,8 @@ const listTriggersStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -95,7 +95,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -104,8 +104,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -149,7 +149,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -191,3 +191,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers_test.go b/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers_test.go index ac3efb433711..ecec9350400c 100644 --- a/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers_test.go +++ b/internal/tools/postgres/postgreslisttriggers/postgreslisttriggers_test.go @@ -17,7 +17,6 @@ package postgreslisttriggers_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgreslistTriggers(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-triggers - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-triggers + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslisttriggers.Config{ Name: "example_tool", - Kind: "postgres-list-triggers", + Type: "postgres-list-triggers", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgreslistTriggers(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-triggers - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-triggers + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslisttriggers.Config{ Name: "example_tool", - Kind: "postgres-list-triggers", + Type: "postgres-list-triggers", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgreslistTriggers(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslistviews/postgreslistviews.go b/internal/tools/postgres/postgreslistviews/postgreslistviews.go index fa4c897da16c..fa2f8c49e838 100644 --- a/internal/tools/postgres/postgreslistviews/postgreslistviews.go +++ b/internal/tools/postgres/postgreslistviews/postgreslistviews.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-list-views" +const resourceType string = "postgres-list-views" const listViewsStatement = ` WITH list_views AS ( @@ -50,8 +50,8 @@ const listViewsStatement = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -70,7 +70,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -79,8 +79,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -119,7 +119,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -165,3 +165,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslistviews/postgreslistviews_test.go b/internal/tools/postgres/postgreslistviews/postgreslistviews_test.go index ffa234569fee..660a77a431bd 100644 --- a/internal/tools/postgres/postgreslistviews/postgreslistviews_test.go +++ b/internal/tools/postgres/postgreslistviews/postgreslistviews_test.go @@ -17,7 +17,6 @@ package postgreslistviews_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresListViews(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-views - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-list-views + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslistviews.Config{ Name: "example_tool", - Kind: "postgres-list-views", + Type: "postgres-list-views", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresListViews(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-list-views - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-list-views + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslistviews.Config{ Name: "example_tool", - Kind: "postgres-list-views", + Type: "postgres-list-views", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresListViews(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions.go b/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions.go index 2faa16d2a034..6491c676ff22 100644 --- a/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions.go +++ b/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-long-running-transactions" +const resourceType string = "postgres-long-running-transactions" const longRunningTransactions = ` SELECT @@ -57,8 +57,8 @@ const longRunningTransactions = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -77,7 +77,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -86,8 +86,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -131,7 +131,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -173,3 +173,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions_test.go b/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions_test.go index d1809933dae7..58fc3c8454c2 100644 --- a/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions_test.go +++ b/internal/tools/postgres/postgreslongrunningtransactions/postgreslongrunningtransactions_test.go @@ -17,7 +17,6 @@ package postgreslongrunningtransactions_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresLongRunningTransactions(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-long-running-transactions - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-long-running-transactions + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgreslongrunningtransactions.Config{ Name: "example_tool", - Kind: "postgres-long-running-transactions", + Type: "postgres-long-running-transactions", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresLongRunningTransactions(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-long-running-transactions - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-long-running-transactions + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgreslongrunningtransactions.Config{ Name: "example_tool", - Kind: "postgres-long-running-transactions", + Type: "postgres-long-running-transactions", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,11 @@ func TestParseFromYamlPostgresLongRunningTransactions(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats.go b/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats.go index b30f41e2b9dd..393b6a9016f7 100644 --- a/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats.go +++ b/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats.go @@ -26,7 +26,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-replication-stats" +const resourceType string = "postgres-replication-stats" const replicationStats = ` SELECT @@ -47,8 +47,8 @@ const replicationStats = ` ` func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -67,7 +67,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -76,8 +76,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -118,7 +118,7 @@ func (t Tool) ToConfig() tools.ToolConfig { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -160,3 +160,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.allParams +} diff --git a/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats_test.go b/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats_test.go index 1958d428956b..87952ecee60b 100644 --- a/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats_test.go +++ b/internal/tools/postgres/postgresreplicationstats/postgresreplicationstats_test.go @@ -17,7 +17,6 @@ package postgresreplicationstats_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlPostgresReplicationStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-replication-stats - source: my-postgres-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: postgres-replication-stats + source: my-postgres-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": postgresreplicationstats.Config{ Name: "example_tool", - Kind: "postgres-replication-stats", + Type: "postgres-replication-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,16 +58,16 @@ func TestParseFromYamlPostgresReplicationStats(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-replication-stats - source: my-postgres-instance - description: some description + kind: tools + name: example_tool + type: postgres-replication-stats + source: my-postgres-instance + description: some description `, want: server.ToolConfigs{ "example_tool": postgresreplicationstats.Config{ Name: "example_tool", - Kind: "postgres-replication-stats", + Type: "postgres-replication-stats", Source: "my-postgres-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlPostgresReplicationStats(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/postgres/postgressql/postgressql.go b/internal/tools/postgres/postgressql/postgressql.go index ab2464ddf9f0..8614af309292 100644 --- a/internal/tools/postgres/postgressql/postgressql.go +++ b/internal/tools/postgres/postgressql/postgressql.go @@ -26,11 +26,11 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -const kind string = "postgres-sql" +const resourceType string = "postgres-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -144,3 +144,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/postgres/postgressql/postgressql_test.go b/internal/tools/postgres/postgressql/postgressql_test.go index c29152ad9bb8..76d8b88f7671 100644 --- a/internal/tools/postgres/postgressql/postgressql_test.go +++ b/internal/tools/postgres/postgressql/postgressql_test.go @@ -17,7 +17,6 @@ package postgressql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlPostgres(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: postgres-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlPostgres(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -106,33 +102,33 @@ func TestParseFromYamlWithTemplateParamsPostgres(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: postgres-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: name - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: postgres-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: name + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": postgressql.Config{ Name: "example_tool", - Kind: "postgres-sql", + Type: "postgres-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -150,15 +146,12 @@ func TestParseFromYamlWithTemplateParamsPostgres(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/redis/redis.go b/internal/tools/redis/redis.go index e322306babe0..2550411e4e9d 100644 --- a/internal/tools/redis/redis.go +++ b/internal/tools/redis/redis.go @@ -25,11 +25,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "redis" +const resourceType string = "redis" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Commands [][]string `yaml:"commands" validate:"required"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -85,7 +85,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -162,3 +162,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/redis/redis_test.go b/internal/tools/redis/redis_test.go index 5ee4ce38414c..88b50d827473 100644 --- a/internal/tools/redis/redis_test.go +++ b/internal/tools/redis/redis_test.go @@ -17,7 +17,6 @@ package redis_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,23 +37,23 @@ func TestParseFromYamlRedis(t *testing.T) { { desc: "basic example", in: ` - tools: - redis_tool: - kind: redis - source: my-redis-instance - description: some description - commands: - - [SET, greeting, "hello, {{.name}}"] - - [GET, id] - parameters: - - name: name - type: string - description: user name + kind: tools + name: redis_tool + type: redis + source: my-redis-instance + description: some description + commands: + - [SET, greeting, "hello, {{.name}}"] + - [GET, id] + parameters: + - name: name + type: string + description: user name `, want: server.ToolConfigs{ "redis_tool": redis.Config{ Name: "redis_tool", - Kind: "redis", + Type: "redis", Source: "my-redis-instance", Description: "some description", AuthRequired: []string{}, @@ -68,15 +67,11 @@ func TestParseFromYamlRedis(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/serverlessspark/createbatch/config.go b/internal/tools/serverlessspark/createbatch/config.go index bcbf611584ee..229ddef9363f 100644 --- a/internal/tools/serverlessspark/createbatch/config.go +++ b/internal/tools/serverlessspark/createbatch/config.go @@ -43,7 +43,7 @@ type compatibleSource interface { // Initialize implementation. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` RuntimeConfig *dataprocpb.RuntimeConfig `yaml:"runtimeConfig"` @@ -56,7 +56,7 @@ func NewConfig(ctx context.Context, name string, decoder *yaml.Decoder) (Config, // conversion for RuntimeConfig and EnvironmentConfig. var ymlCfg struct { Name string `yaml:"name"` - Kind string `yaml:"kind"` + Type string `yaml:"type"` Source string `yaml:"source"` Description string `yaml:"description"` RuntimeConfig any `yaml:"runtimeConfig"` @@ -70,7 +70,7 @@ func NewConfig(ctx context.Context, name string, decoder *yaml.Decoder) (Config, cfg := Config{ Name: name, - Kind: ymlCfg.Kind, + Type: ymlCfg.Type, Source: ymlCfg.Source, Description: ymlCfg.Description, AuthRequired: ymlCfg.AuthRequired, diff --git a/internal/tools/serverlessspark/createbatch/tool.go b/internal/tools/serverlessspark/createbatch/tool.go index dca7081aa60e..ad43b86d8870 100644 --- a/internal/tools/serverlessspark/createbatch/tool.go +++ b/internal/tools/serverlessspark/createbatch/tool.go @@ -34,7 +34,7 @@ type BatchBuilder interface { func NewTool(cfg Config, originalCfg tools.ToolConfig, srcs map[string]sources.Source, builder BatchBuilder) (*Tool, error) { desc := cfg.Description if desc == "" { - desc = fmt.Sprintf("Creates a Serverless Spark (aka Dataproc Serverless) %s operation.", cfg.Kind) + desc = fmt.Sprintf("Creates a Serverless Spark (aka Dataproc Serverless) %s operation.", cfg.Type) } allParameters := builder.Parameters() @@ -66,7 +66,7 @@ type Tool struct { } func (t *Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -126,3 +126,7 @@ func (t *Tool) ToConfig() tools.ToolConfig { func (t *Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t *Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch.go b/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch.go index fe072f076078..9a8af0a13e0b 100644 --- a/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch.go +++ b/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind = "serverless-spark-cancel-batch" +const resourceType = "serverless-spark-cancel-batch" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the unique name for this tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the unique name for this tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance. @@ -100,7 +100,7 @@ type Tool struct { // Invoke executes the tool's operation. func (t *Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -147,3 +147,7 @@ func (t *Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t *Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch_test.go b/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch_test.go index 5348399a321c..463fbf33e1c7 100644 --- a/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch_test.go +++ b/internal/tools/serverlessspark/serverlesssparkcancelbatch/serverlesssparkcancelbatch_test.go @@ -17,7 +17,6 @@ package serverlesssparkcancelbatch_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: serverless-spark-cancel-batch - source: my-instance - description: some description + kind: tools + name: example_tool + type: serverless-spark-cancel-batch + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": serverlesssparkcancelbatch.Config{ Name: "example_tool", - Kind: "serverless-spark-cancel-batch", + Type: "serverless-spark-cancel-batch", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got, yaml.Strict()) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/serverlessspark/serverlesssparkcreatepysparkbatch/serverlesssparkcreatepysparkbatch.go b/internal/tools/serverlessspark/serverlesssparkcreatepysparkbatch/serverlesssparkcreatepysparkbatch.go index d07fa01b92ea..c0801059f8b4 100644 --- a/internal/tools/serverlessspark/serverlesssparkcreatepysparkbatch/serverlesssparkcreatepysparkbatch.go +++ b/internal/tools/serverlessspark/serverlesssparkcreatepysparkbatch/serverlesssparkcreatepysparkbatch.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind = "serverless-spark-create-pyspark-batch" +const resourceType = "serverless-spark-create-pyspark-batch" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,9 +49,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the unique name for this tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the unique name for this tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance. diff --git a/internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go b/internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go index e16b1904e296..403ea1573a88 100644 --- a/internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go +++ b/internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind = "serverless-spark-create-spark-batch" +const resourceType = "serverless-spark-create-spark-batch" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,9 +49,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the unique name for this tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the unique name for this tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance. diff --git a/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch.go b/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch.go index 85d1247fffa1..a892c4746f44 100644 --- a/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch.go +++ b/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind = "serverless-spark-get-batch" +const resourceType = "serverless-spark-get-batch" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -59,9 +59,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the unique name for this tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the unique name for this tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance. @@ -100,7 +100,7 @@ type Tool struct { // Invoke executes the tool's operation. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -146,3 +146,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch_test.go b/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch_test.go index f7589f7b077d..e47ec519fbda 100644 --- a/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch_test.go +++ b/internal/tools/serverlessspark/serverlesssparkgetbatch/serverlesssparkgetbatch_test.go @@ -17,7 +17,6 @@ package serverlesssparkgetbatch_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: serverless-spark-get-batch - source: my-instance - description: some description + kind: tools + name: example_tool + type: serverless-spark-get-batch + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": serverlesssparkgetbatch.Config{ Name: "example_tool", - Kind: "serverless-spark-get-batch", + Type: "serverless-spark-get-batch", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got, yaml.Strict()) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches.go b/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches.go index 3757b9a6e655..e064d83f072a 100644 --- a/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches.go +++ b/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind = "serverless-spark-list-batches" +const resourceType = "serverless-spark-list-batches" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -58,9 +58,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the unique name for this tool. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the unique name for this tool. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize creates a new Tool instance. @@ -101,7 +101,7 @@ type Tool struct { // Invoke executes the tool's operation. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -151,3 +151,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches_test.go b/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches_test.go index 95a11237408a..5b465baaa443 100644 --- a/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches_test.go +++ b/internal/tools/serverlessspark/serverlesssparklistbatches/serverlesssparklistbatches_test.go @@ -17,7 +17,6 @@ package serverlesssparklistbatches_test import ( "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: serverless-spark-list-batches - source: my-instance - description: some description + kind: tools + name: example_tool + type: serverless-spark-list-batches + source: my-instance + description: some description `, want: server.ToolConfigs{ "example_tool": serverlesssparklistbatches.Config{ Name: "example_tool", - Kind: "serverless-spark-list-batches", + Type: "serverless-spark-list-batches", Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got, yaml.Strict()) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/serverlessspark/testutils/testutils.go b/internal/tools/serverlessspark/testutils/testutils.go index a8a2cfc5a3da..d9ff086445ba 100644 --- a/internal/tools/serverlessspark/testutils/testutils.go +++ b/internal/tools/serverlessspark/testutils/testutils.go @@ -20,7 +20,6 @@ import ( "testing" dataproc "cloud.google.com/go/dataproc/v2/apiv1/dataprocpb" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -30,7 +29,7 @@ import ( ) // RunParseFromYAMLTests runs a suite of tests for parsing tool configurations from YAML. -func RunParseFromYAMLTests(t *testing.T, kind string, newConfig func(c createbatch.Config) tools.ToolConfig) { +func RunParseFromYAMLTests(t *testing.T, resourceType string, newConfig func(c createbatch.Config) tools.ToolConfig) { t.Helper() ctx, err := testutils.ContextWithNewLogger() if err != nil { @@ -46,16 +45,16 @@ func RunParseFromYAMLTests(t *testing.T, kind string, newConfig func(c createbat { desc: "basic example", in: fmt.Sprintf(` - tools: - example_tool: - kind: %s - source: my-instance - description: some description - `, kind), + kind: tools + name: example_tool + type: %s + source: my-instance + description: some description + `, resourceType), want: server.ToolConfigs{ "example_tool": newConfig(createbatch.Config{ Name: "example_tool", - Kind: kind, + Type: resourceType, Source: "my-instance", Description: "some description", AuthRequired: []string{}, @@ -65,22 +64,22 @@ func RunParseFromYAMLTests(t *testing.T, kind string, newConfig func(c createbat { desc: "detailed config", in: fmt.Sprintf(` - tools: - example_tool: - kind: %s - source: my-instance - description: some description - runtimeConfig: - properties: - "spark.driver.memory": "1g" - environmentConfig: - executionConfig: - networkUri: "my-network" - `, kind), + kind: tools + name: example_tool + type: %s + source: my-instance + description: some description + runtimeConfig: + properties: + "spark.driver.memory": "1g" + environmentConfig: + executionConfig: + networkUri: "my-network" + `, resourceType), want: server.ToolConfigs{ "example_tool": newConfig(createbatch.Config{ Name: "example_tool", - Kind: kind, + Type: resourceType, Source: "my-instance", Description: "some description", RuntimeConfig: &dataproc.RuntimeConfig{ @@ -98,36 +97,33 @@ func RunParseFromYAMLTests(t *testing.T, kind string, newConfig func(c createbat { desc: "invalid runtime config", in: fmt.Sprintf(` - tools: - example_tool: - kind: %s - source: my-instance - description: some description - runtimeConfig: - invalidField: true - `, kind), + kind: tools + name: example_tool + type: %s + source: my-instance + description: some description + runtimeConfig: + invalidField: true + `, resourceType), wantErr: "unmarshal runtimeConfig", }, { desc: "invalid environment config", in: fmt.Sprintf(` - tools: - example_tool: - kind: %s - source: my-instance - description: some description - environmentConfig: - invalidField: true - `, kind), + kind: tools + name: example_tool + type: %s + source: my-instance + description: some description + environmentConfig: + invalidField: true + `, resourceType), wantErr: "unmarshal environmentConfig", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got, yaml.Strict()) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if tc.wantErr != "" { if err == nil { t.Fatal("expected error, got nil") @@ -141,7 +137,7 @@ func RunParseFromYAMLTests(t *testing.T, kind string, newConfig func(c createbat t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools, protocmp.Transform()); diff != "" { + if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql.go b/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql.go index dda577f2eb8a..384263893190 100644 --- a/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql.go +++ b/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "singlestore-execute-sql" +const resourceType string = "singlestore-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { // Config represents the configuration for the singlestore-execute-sql tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -60,9 +60,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool configuration. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool configuration. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize sets up the Tool using the provided sources map. @@ -99,7 +99,7 @@ func (t Tool) ToConfig() tools.ToolConfig { // Invoke executes the provided SQL query using the tool's database connection and returns the results. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -115,7 +115,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, "executing `%s` tool query: %s", kind, sql) + logger.DebugContext(ctx, "executing `%s` tool query: %s", resourceType, sql) return source.RunSQL(ctx, sql, nil) } @@ -146,3 +146,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql_test.go b/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql_test.go index f68455cf427e..208a36934286 100644 --- a/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql_test.go +++ b/internal/tools/singlestore/singlestoreexecutesql/singlestoreexecutesql_test.go @@ -17,14 +17,13 @@ package singlestoreexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" "github.com/googleapis/genai-toolbox/internal/tools/singlestore/singlestoreexecutesql" ) -func TestParseFromYamlExecuteSql(t *testing.T) { +func TestParseFromYaml(t *testing.T) { ctx, err := testutils.ContextWithNewLogger() if err != nil { t.Fatalf("unexpected error: %s", err) @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: singlestore-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: singlestore-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": singlestoreexecutesql.Config{ Name: "example_tool", - Kind: "singlestore-execute-sql", + Type: "singlestore-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,11 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/singlestore/singlestoresql/singlestoresql.go b/internal/tools/singlestore/singlestoresql/singlestoresql.go index ff5862ef264d..4334ee2db16c 100644 --- a/internal/tools/singlestore/singlestoresql/singlestoresql.go +++ b/internal/tools/singlestore/singlestoresql/singlestoresql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "singlestore-sql" +const resourceType string = "singlestore-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { // Config defines the configuration for a SingleStore SQL tool. type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -62,9 +62,9 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -// ToolConfigKind returns the kind of the tool configuration. -func (cfg Config) ToolConfigKind() string { - return kind +// ToolConfigType returns the type of the tool configuration. +func (cfg Config) ToolConfigType() string { + return resourceType } // Initialize sets up and returns a new Tool instance based on the provided configuration and available sources. @@ -127,7 +127,7 @@ func (t Tool) ToConfig() tools.ToolConfig { // - A slice of maps, where each map represents a row with column names as keys. // - An error if template resolution, parameter extraction, query execution, or result processing fails. func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -174,3 +174,7 @@ func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (boo func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/singlestore/singlestoresql/singlestoresql_test.go b/internal/tools/singlestore/singlestoresql/singlestoresql_test.go index a4c7559cf4a4..e6204d8552c3 100644 --- a/internal/tools/singlestore/singlestoresql/singlestoresql_test.go +++ b/internal/tools/singlestore/singlestoresql/singlestoresql_test.go @@ -17,7 +17,6 @@ package singlestoresql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -25,7 +24,7 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -func TestParseFromYamlSingleStore(t *testing.T) { +func TestParseFromYaml(t *testing.T) { ctx, err := testutils.ContextWithNewLogger() if err != nil { t.Fatalf("unexpected error: %s", err) @@ -38,30 +37,30 @@ func TestParseFromYamlSingleStore(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: singlestore-sql - source: my-singlestore-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: singlestore-sql + source: my-singlestore-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": singlestoresql.Config{ Name: "example_tool", - Kind: "singlestore-sql", + Type: "singlestore-sql", Source: "my-singlestore-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -74,72 +73,44 @@ func TestParseFromYamlSingleStore(t *testing.T) { }, }, }, - } - for _, tc := range tcs { - t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) - if err != nil { - t.Fatalf("unable to unmarshal: %s", err) - } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { - t.Fatalf("incorrect parse: diff %v", diff) - } - }) - } -} - -func TestParseFromYamlWithTemplateParamsSingleStore(t *testing.T) { - ctx, err := testutils.ContextWithNewLogger() - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - tcs := []struct { - desc string - in string - want server.ToolConfigs - }{ { - desc: "basic example", + desc: "with template params", in: ` - tools: - example_tool: - kind: singlestore-sql - source: my-singlestore-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: singlestore-sql + source: my-singlestore-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": singlestoresql.Config{ Name: "example_tool", - Kind: "singlestore-sql", + Type: "singlestore-sql", Source: "my-singlestore-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -159,15 +130,11 @@ func TestParseFromYamlWithTemplateParamsSingleStore(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql.go b/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql.go index ce089a87cbfa..fcd2c44d126d 100644 --- a/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql.go +++ b/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/jmoiron/sqlx" ) -const kind string = "snowflake-execute-sql" +const resourceType string = "snowflake-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -106,7 +106,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -141,3 +141,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql_test.go b/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql_test.go index b9cd5da63b22..98050127016e 100644 --- a/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql_test.go +++ b/internal/tools/snowflake/snowflakeexecutesql/snowflakeexecutesql_test.go @@ -17,7 +17,6 @@ package snowflakeexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - my-snowflake-tool: - kind: snowflake-execute-sql - source: my-snowflake-source - description: Execute SQL on Snowflake + kind: tools + name: my-snowflake-tool + type: snowflake-execute-sql + source: my-snowflake-source + description: Execute SQL on Snowflake `, want: server.ToolConfigs{ "my-snowflake-tool": snowflakeexecutesql.Config{ Name: "my-snowflake-tool", - Kind: "snowflake-execute-sql", + Type: "snowflake-execute-sql", Source: "my-snowflake-source", Description: "Execute SQL on Snowflake", AuthRequired: []string{}, @@ -56,15 +55,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -84,21 +80,18 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "missing required field", in: ` - tools: - my-snowflake-tool: - kind: snowflake-execute-sql - source: my-snowflake-source + kind: tools + name: my-snowflake-tool + type: snowflake-execute-sql + source: my-snowflake-source `, - err: "unable to parse tool \"my-snowflake-tool\" as kind \"snowflake-execute-sql\": Key: 'Config.Description' Error:Field validation for 'Description' failed on the 'required' tag", + err: "error unmarshaling tools: unable to parse tool \"my-snowflake-tool\" as type \"snowflake-execute-sql\": Key: 'Config.Description' Error:Field validation for 'Description' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/snowflake/snowflakesql/snowflakesql.go b/internal/tools/snowflake/snowflakesql/snowflakesql.go index c53e265a3a57..4b74033ed871 100644 --- a/internal/tools/snowflake/snowflakesql/snowflakesql.go +++ b/internal/tools/snowflake/snowflakesql/snowflakesql.go @@ -26,11 +26,11 @@ import ( "github.com/jmoiron/sqlx" ) -const kind string = "snowflake-sql" +const resourceType string = "snowflake-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -145,3 +145,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/snowflake/snowflakesql/snowflakesql_test.go b/internal/tools/snowflake/snowflakesql/snowflakesql_test.go index 34321084826a..520cae320762 100644 --- a/internal/tools/snowflake/snowflakesql/snowflakesql_test.go +++ b/internal/tools/snowflake/snowflakesql/snowflakesql_test.go @@ -17,7 +17,6 @@ package snowflakesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,17 +36,17 @@ func TestParseFromYaml(t *testing.T) { { desc: "basic example", in: ` - tools: - my-snowflake-tool: - kind: snowflake-sql - source: my-snowflake-source - description: Execute parameterized SQL on Snowflake - statement: SELECT * FROM my_table WHERE id = $1 + kind: tools + name: my-snowflake-tool + type: snowflake-sql + source: my-snowflake-source + description: Execute parameterized SQL on Snowflake + statement: SELECT * FROM my_table WHERE id = $1 `, want: server.ToolConfigs{ "my-snowflake-tool": snowflakesql.Config{ Name: "my-snowflake-tool", - Kind: "snowflake-sql", + Type: "snowflake-sql", Source: "my-snowflake-source", Description: "Execute parameterized SQL on Snowflake", Statement: "SELECT * FROM my_table WHERE id = $1", @@ -60,15 +59,12 @@ func TestParseFromYaml(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -88,22 +84,19 @@ func TestFailParseFromYaml(t *testing.T) { { desc: "missing required field", in: ` - tools: - my-snowflake-tool: - kind: snowflake-sql - source: my-snowflake-source - description: Execute parameterized SQL on Snowflake + kind: tools + name: my-snowflake-tool + type: snowflake-sql + source: my-snowflake-source + description: Execute parameterized SQL on Snowflake `, - err: "unable to parse tool \"my-snowflake-tool\" as kind \"snowflake-sql\": Key: 'Config.Statement' Error:Field validation for 'Statement' failed on the 'required' tag", + err: "error unmarshaling tools: unable to parse tool \"my-snowflake-tool\" as type \"snowflake-sql\": Key: 'Config.Statement' Error:Field validation for 'Statement' failed on the 'required' tag", }, } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expect parsing to fail") } diff --git a/internal/tools/spanner/spannerexecutesql/spannerexecutesql.go b/internal/tools/spanner/spannerexecutesql/spannerexecutesql.go index 8a5f6c6d0cb8..2ae5bbc5d33e 100644 --- a/internal/tools/spanner/spannerexecutesql/spannerexecutesql.go +++ b/internal/tools/spanner/spannerexecutesql/spannerexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "spanner-execute-sql" +const resourceType string = "spanner-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -92,7 +92,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -108,7 +108,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, t.ReadOnly, sql, nil) } @@ -143,3 +143,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/spanner/spannerexecutesql/spannerexecutesql_test.go b/internal/tools/spanner/spannerexecutesql/spannerexecutesql_test.go index a406b378802e..76e98e8346da 100644 --- a/internal/tools/spanner/spannerexecutesql/spannerexecutesql_test.go +++ b/internal/tools/spanner/spannerexecutesql/spannerexecutesql_test.go @@ -17,7 +17,6 @@ package spannerexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: spanner-execute-sql - source: my-spanner-instance - description: some description + kind: tools + name: example_tool + type: spanner-execute-sql + source: my-spanner-instance + description: some description `, want: server.ToolConfigs{ "example_tool": spannerexecutesql.Config{ Name: "example_tool", - Kind: "spanner-execute-sql", + Type: "spanner-execute-sql", Source: "my-spanner-instance", Description: "some description", AuthRequired: []string{}, @@ -57,17 +56,17 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "read only set to true", in: ` - tools: - example_tool: - kind: spanner-execute-sql - source: my-spanner-instance - description: some description - readOnly: true + kind: tools + name: example_tool + type: spanner-execute-sql + source: my-spanner-instance + description: some description + readOnly: true `, want: server.ToolConfigs{ "example_tool": spannerexecutesql.Config{ Name: "example_tool", - Kind: "spanner-execute-sql", + Type: "spanner-execute-sql", Source: "my-spanner-instance", Description: "some description", AuthRequired: []string{}, @@ -78,15 +77,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs.go b/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs.go index 6db7da58f9c6..2f993b1a9805 100644 --- a/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs.go +++ b/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "spanner-list-graphs" +const resourceType string = "spanner-list-graphs" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -106,7 +106,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -163,6 +163,10 @@ func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, return "Authorization", nil } +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} + // GoogleSQL statement for listing graphs const googleSQLStatement = ` WITH FilterGraphNames AS ( diff --git a/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs_test.go b/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs_test.go index eb4cca9e954b..1dbdd8caad59 100644 --- a/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs_test.go +++ b/internal/tools/spanner/spannerlistgraphs/spannerlistgraphs_test.go @@ -17,7 +17,6 @@ package spannerlistgraphs_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlListGraphs(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: spanner-list-graphs - source: my-spanner-instance - description: Lists graphs in the database + kind: tools + name: example_tool + type: spanner-list-graphs + source: my-spanner-instance + description: Lists graphs in the database `, want: server.ToolConfigs{ "example_tool": spannerlistgraphs.Config{ Name: "example_tool", - Kind: "spanner-list-graphs", + Type: "spanner-list-graphs", Source: "my-spanner-instance", Description: "Lists graphs in the database", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlListGraphs(t *testing.T) { { desc: "with auth required", in: ` - tools: - example_tool: - kind: spanner-list-graphs - source: my-spanner-instance - description: Lists graphs in the database - authRequired: - - auth1 - - auth2 + kind: tools + name: example_tool + type: spanner-list-graphs + source: my-spanner-instance + description: Lists graphs in the database + authRequired: + - auth1 + - auth2 `, want: server.ToolConfigs{ "example_tool": spannerlistgraphs.Config{ Name: "example_tool", - Kind: "spanner-list-graphs", + Type: "spanner-list-graphs", Source: "my-spanner-instance", Description: "Lists graphs in the database", AuthRequired: []string{"auth1", "auth2"}, @@ -78,15 +77,15 @@ func TestParseFromYamlListGraphs(t *testing.T) { { desc: "minimal config", in: ` - tools: - example_tool: - kind: spanner-list-graphs - source: my-spanner-instance + kind: tools + name: example_tool + type: spanner-list-graphs + source: my-spanner-instance `, want: server.ToolConfigs{ "example_tool": spannerlistgraphs.Config{ Name: "example_tool", - Kind: "spanner-list-graphs", + Type: "spanner-list-graphs", Source: "my-spanner-instance", Description: "", AuthRequired: []string{}, @@ -96,15 +95,12 @@ func TestParseFromYamlListGraphs(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/spanner/spannerlisttables/spannerlisttables.go b/internal/tools/spanner/spannerlisttables/spannerlisttables.go index 9c9d1322c620..998609dbf7f4 100644 --- a/internal/tools/spanner/spannerlisttables/spannerlisttables.go +++ b/internal/tools/spanner/spannerlisttables/spannerlisttables.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "spanner-list-tables" +const resourceType string = "spanner-list-tables" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description"` AuthRequired []string `yaml:"authRequired"` @@ -60,8 +60,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -118,7 +118,7 @@ func getStatement(dialect string) string { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -189,6 +189,10 @@ func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, return "Authorization", nil } +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} + // PostgreSQL statement for listing tables const postgresqlStatement = ` WITH table_info_cte AS ( diff --git a/internal/tools/spanner/spannerlisttables/spannerlisttables_test.go b/internal/tools/spanner/spannerlisttables/spannerlisttables_test.go index da4a9885c509..0bc6fce5cdfa 100644 --- a/internal/tools/spanner/spannerlisttables/spannerlisttables_test.go +++ b/internal/tools/spanner/spannerlisttables/spannerlisttables_test.go @@ -17,7 +17,6 @@ package spannerlisttables_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,16 +36,16 @@ func TestParseFromYamlListTables(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: spanner-list-tables - source: my-spanner-instance - description: Lists tables in the database + kind: tools + name: example_tool + type: spanner-list-tables + source: my-spanner-instance + description: Lists tables in the database `, want: server.ToolConfigs{ "example_tool": spannerlisttables.Config{ Name: "example_tool", - Kind: "spanner-list-tables", + Type: "spanner-list-tables", Source: "my-spanner-instance", Description: "Lists tables in the database", AuthRequired: []string{}, @@ -56,19 +55,19 @@ func TestParseFromYamlListTables(t *testing.T) { { desc: "with auth required", in: ` - tools: - example_tool: - kind: spanner-list-tables - source: my-spanner-instance - description: Lists tables in the database - authRequired: - - auth1 - - auth2 + kind: tools + name: example_tool + type: spanner-list-tables + source: my-spanner-instance + description: Lists tables in the database + authRequired: + - auth1 + - auth2 `, want: server.ToolConfigs{ "example_tool": spannerlisttables.Config{ Name: "example_tool", - Kind: "spanner-list-tables", + Type: "spanner-list-tables", Source: "my-spanner-instance", Description: "Lists tables in the database", AuthRequired: []string{"auth1", "auth2"}, @@ -78,15 +77,15 @@ func TestParseFromYamlListTables(t *testing.T) { { desc: "minimal config", in: ` - tools: - example_tool: - kind: spanner-list-tables - source: my-spanner-instance + kind: tools + name: example_tool + type: spanner-list-tables + source: my-spanner-instance `, want: server.ToolConfigs{ "example_tool": spannerlisttables.Config{ Name: "example_tool", - Kind: "spanner-list-tables", + Type: "spanner-list-tables", Source: "my-spanner-instance", Description: "", AuthRequired: []string{}, @@ -96,15 +95,12 @@ func TestParseFromYamlListTables(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/spanner/spannersql/spanner_test.go b/internal/tools/spanner/spannersql/spanner_test.go index 5f86bcae6f94..227c21b68a0e 100644 --- a/internal/tools/spanner/spannersql/spanner_test.go +++ b/internal/tools/spanner/spannersql/spanner_test.go @@ -17,7 +17,6 @@ package spannersql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,22 +37,22 @@ func TestParseFromYamlSpanner(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: spanner-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description + kind: tools + name: example_tool + type: spanner-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description `, want: server.ToolConfigs{ "example_tool": spannersql.Config{ Name: "example_tool", - Kind: "spanner-sql", + Type: "spanner-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -67,23 +66,23 @@ func TestParseFromYamlSpanner(t *testing.T) { { desc: "read only set to true", in: ` - tools: - example_tool: - kind: spanner-sql - source: my-pg-instance - description: some description - readOnly: true - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description + kind: tools + name: example_tool + type: spanner-sql + source: my-pg-instance + description: some description + readOnly: true + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description `, want: server.ToolConfigs{ "example_tool": spannersql.Config{ Name: "example_tool", - Kind: "spanner-sql", + Type: "spanner-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -98,15 +97,12 @@ func TestParseFromYamlSpanner(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -127,33 +123,33 @@ func TestParseFromYamlWithTemplateParamsSpanner(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: spanner-sql - source: my-pg-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: spanner-sql + source: my-pg-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": spannersql.Config{ Name: "example_tool", - Kind: "spanner-sql", + Type: "spanner-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -171,23 +167,23 @@ func TestParseFromYamlWithTemplateParamsSpanner(t *testing.T) { { desc: "read only set to true", in: ` - tools: - example_tool: - kind: spanner-sql - source: my-pg-instance - description: some description - readOnly: true - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: country - type: string - description: some description + kind: tools + name: example_tool + type: spanner-sql + source: my-pg-instance + description: some description + readOnly: true + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: country + type: string + description: some description `, want: server.ToolConfigs{ "example_tool": spannersql.Config{ Name: "example_tool", - Kind: "spanner-sql", + Type: "spanner-sql", Source: "my-pg-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -202,15 +198,12 @@ func TestParseFromYamlWithTemplateParamsSpanner(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/spanner/spannersql/spannersql.go b/internal/tools/spanner/spannersql/spannersql.go index 7da22f55626c..75eb79a3a7de 100644 --- a/internal/tools/spanner/spannersql/spannersql.go +++ b/internal/tools/spanner/spannersql/spannersql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "spanner-sql" +const resourceType string = "spanner-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -51,7 +51,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -64,8 +64,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -108,7 +108,7 @@ func getMapParams(params parameters.ParamValues, dialect string) (map[string]int } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -185,3 +185,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql.go b/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql.go index 682959d045d2..49f338d4d555 100644 --- a/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql.go +++ b/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "sqlite-execute-sql" +const resourceType string = "sqlite-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -89,7 +89,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -142,3 +142,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql_test.go b/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql_test.go index 63079a883eee..f45402c86d87 100644 --- a/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql_test.go +++ b/internal/tools/sqlite/sqliteexecutesql/sqliteexecutesql_test.go @@ -17,7 +17,6 @@ package sqliteexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,19 +37,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: sqlite-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: sqlite-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": sqliteexecutesql.Config{ Name: "example_tool", - Kind: "sqlite-execute-sql", + Type: "sqlite-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -60,15 +59,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/sqlite/sqlitesql/sqlitesql.go b/internal/tools/sqlite/sqlitesql/sqlitesql.go index f582c20841ea..c8c2da6eb467 100644 --- a/internal/tools/sqlite/sqlitesql/sqlitesql.go +++ b/internal/tools/sqlite/sqlitesql/sqlitesql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "sqlite-sql" +const resourceType string = "sqlite-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -143,3 +143,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/sqlite/sqlitesql/sqlitesql_test.go b/internal/tools/sqlite/sqlitesql/sqlitesql_test.go index eea6fddf4f24..6aa2968534b0 100644 --- a/internal/tools/sqlite/sqlitesql/sqlitesql_test.go +++ b/internal/tools/sqlite/sqlitesql/sqlitesql_test.go @@ -17,7 +17,6 @@ package sqlitesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -39,30 +38,30 @@ func TestParseFromYamlSQLite(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: sqlite-sql - source: my-sqlite-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: sqlite-sql + source: my-sqlite-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": sqlitesql.Config{ Name: "example_tool", - Kind: "sqlite-sql", + Type: "sqlite-sql", Source: "my-sqlite-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -78,15 +77,12 @@ func TestParseFromYamlSQLite(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -107,41 +103,41 @@ func TestParseFromYamlWithTemplateSqlite(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: sqlite-sql - source: my-sqlite-db - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: sqlite-sql + source: my-sqlite-db + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": sqlitesql.Config{ Name: "example_tool", - Kind: "sqlite-sql", + Type: "sqlite-sql", Source: "my-sqlite-db", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -161,15 +157,12 @@ func TestParseFromYamlWithTemplateSqlite(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/tidb/tidbexecutesql/tidbexecutesql.go b/internal/tools/tidb/tidbexecutesql/tidbexecutesql.go index b530399d39f9..a2fae8251e2b 100644 --- a/internal/tools/tidb/tidbexecutesql/tidbexecutesql.go +++ b/internal/tools/tidb/tidbexecutesql/tidbexecutesql.go @@ -27,11 +27,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "tidb-execute-sql" +const resourceType string = "tidb-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -50,7 +50,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -90,7 +90,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -106,7 +106,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para if err != nil { return nil, fmt.Errorf("error getting logger: %s", err) } - logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", kind, sql)) + logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql)) return source.RunSQL(ctx, sql, nil) } @@ -141,3 +141,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/tidb/tidbexecutesql/tidbexecutesql_test.go b/internal/tools/tidb/tidbexecutesql/tidbexecutesql_test.go index 432743dbd931..a8742d373b42 100644 --- a/internal/tools/tidb/tidbexecutesql/tidbexecutesql_test.go +++ b/internal/tools/tidb/tidbexecutesql/tidbexecutesql_test.go @@ -17,7 +17,6 @@ package tidbexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlExecuteSql(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: tidb-execute-sql - source: my-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: tidb-execute-sql + source: my-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": tidbexecutesql.Config{ Name: "example_tool", - Kind: "tidb-execute-sql", + Type: "tidb-execute-sql", Source: "my-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,12 @@ func TestParseFromYamlExecuteSql(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/tidb/tidbsql/tidbsql.go b/internal/tools/tidb/tidbsql/tidbsql.go index 421db2752737..8c974c629d65 100644 --- a/internal/tools/tidb/tidbsql/tidbsql.go +++ b/internal/tools/tidb/tidbsql/tidbsql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "tidb-sql" +const resourceType string = "tidb-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -145,3 +145,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.AllParams +} diff --git a/internal/tools/tidb/tidbsql/tidbsql_test.go b/internal/tools/tidb/tidbsql/tidbsql_test.go index 4a5c425d0368..65ae5a83aaa7 100644 --- a/internal/tools/tidb/tidbsql/tidbsql_test.go +++ b/internal/tools/tidb/tidbsql/tidbsql_test.go @@ -17,7 +17,6 @@ package tidbsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlTiDB(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: tidb-sql - source: my-tidb-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: tidb-sql + source: my-tidb-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": tidbsql.Config{ Name: "example_tool", - Kind: "tidb-sql", + Type: "tidb-sql", Source: "my-tidb-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -77,15 +76,12 @@ func TestParseFromYamlTiDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -105,41 +101,41 @@ func TestParseFromYamlWithTemplateParamsTiDB(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: tidb-sql - source: my-tidb-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: tidb-sql + source: my-tidb-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": tidbsql.Config{ Name: "example_tool", - Kind: "tidb-sql", + Type: "tidb-sql", Source: "my-tidb-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -159,15 +155,12 @@ func TestParseFromYamlWithTemplateParamsTiDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/tools.go b/internal/tools/tools.go index daadf385b72a..32caac899a51 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -36,34 +36,34 @@ var toolRegistry = make(map[string]ToolConfigFactory) // Register allows individual tool packages to register their configuration // factory function. This is typically called from an init() function in the -// tool's package. It associates a 'kind' string with a function that can +// tool's package. It associates a 'type' string with a function that can // produce the specific ToolConfig type. It returns true if the registration was -// successful, and false if a tool with the same kind was already registered. -func Register(kind string, factory ToolConfigFactory) bool { - if _, exists := toolRegistry[kind]; exists { - // Tool with this kind already exists, do not overwrite. +// successful, and false if a tool with the same type was already registered. +func Register(resourceType string, factory ToolConfigFactory) bool { + if _, exists := toolRegistry[resourceType]; exists { + // Tool with this type already exists, do not overwrite. return false } - toolRegistry[kind] = factory + toolRegistry[resourceType] = factory return true } -// DecodeConfig looks up the registered factory for the given kind and uses it +// DecodeConfig looks up the registered factory for the given type and uses it // to decode the tool configuration. -func DecodeConfig(ctx context.Context, kind string, name string, decoder *yaml.Decoder) (ToolConfig, error) { - factory, found := toolRegistry[kind] +func DecodeConfig(ctx context.Context, resourceType string, name string, decoder *yaml.Decoder) (ToolConfig, error) { + factory, found := toolRegistry[resourceType] if !found { - return nil, fmt.Errorf("unknown tool kind: %q", kind) + return nil, fmt.Errorf("unknown tool type: %q", resourceType) } toolConfig, err := factory(ctx, name, decoder) if err != nil { - return nil, fmt.Errorf("unable to parse tool %q as kind %q: %w", name, kind, err) + return nil, fmt.Errorf("unable to parse tool %q as type %q: %w", name, resourceType, err) } return toolConfig, nil } type ToolConfig interface { - ToolConfigKind() string + ToolConfigType() string Initialize(map[string]sources.Source) (Tool, error) } @@ -95,6 +95,7 @@ type Tool interface { RequiresClientAuthorization(SourceProvider) (bool, error) ToConfig() ToolConfig GetAuthTokenHeaderName(SourceProvider) (string, error) + GetParameters() parameters.Parameters } // SourceProvider defines the minimal view of the server.ResourceManager @@ -160,7 +161,7 @@ func IsAuthorized(authRequiredSources []string, verifiedAuthServices []string) b return false } -func GetCompatibleSource[T any](resourceMgr SourceProvider, sourceName, toolName, toolKind string) (T, error) { +func GetCompatibleSource[T any](resourceMgr SourceProvider, sourceName, toolName, toolType string) (T, error) { var zero T s, ok := resourceMgr.GetSource(sourceName) if !ok { @@ -168,7 +169,7 @@ func GetCompatibleSource[T any](resourceMgr SourceProvider, sourceName, toolName } source, ok := s.(T) if !ok { - return zero, fmt.Errorf("invalid source for %q tool: source %q is not a compatible type", toolKind, sourceName) + return zero, fmt.Errorf("invalid source for %q tool: source %q is not a compatible type", toolType, sourceName) } return source, nil } diff --git a/internal/tools/trino/trinoexecutesql/trinoexecutesql.go b/internal/tools/trino/trinoexecutesql/trinoexecutesql.go index 529590e35e18..a263ef2a11f9 100644 --- a/internal/tools/trino/trinoexecutesql/trinoexecutesql.go +++ b/internal/tools/trino/trinoexecutesql/trinoexecutesql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "trino-execute-sql" +const resourceType string = "trino-execute-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -58,8 +58,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -89,7 +89,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -133,3 +133,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/trino/trinoexecutesql/trinoexecutesql_test.go b/internal/tools/trino/trinoexecutesql/trinoexecutesql_test.go index 0af7ce176226..372654d0ee4e 100644 --- a/internal/tools/trino/trinoexecutesql/trinoexecutesql_test.go +++ b/internal/tools/trino/trinoexecutesql/trinoexecutesql_test.go @@ -17,7 +17,6 @@ package trinoexecutesql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -37,19 +36,19 @@ func TestParseFromYamlTrinoExecuteSQL(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: trino-execute-sql - source: my-trino-instance - description: some description - authRequired: - - my-google-auth-service - - other-auth-service + kind: tools + name: example_tool + type: trino-execute-sql + source: my-trino-instance + description: some description + authRequired: + - my-google-auth-service + - other-auth-service `, want: server.ToolConfigs{ "example_tool": trinoexecutesql.Config{ Name: "example_tool", - Kind: "trino-execute-sql", + Type: "trino-execute-sql", Source: "my-trino-instance", Description: "some description", AuthRequired: []string{"my-google-auth-service", "other-auth-service"}, @@ -59,15 +58,11 @@ func TestParseFromYamlTrinoExecuteSQL(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/trino/trinosql/trinosql.go b/internal/tools/trino/trinosql/trinosql.go index eb75db07ee72..798cb8b13f97 100644 --- a/internal/tools/trino/trinosql/trinosql.go +++ b/internal/tools/trino/trinosql/trinosql.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "trino-sql" +const resourceType string = "trino-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -143,3 +143,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/trino/trinosql/trinosql_test.go b/internal/tools/trino/trinosql/trinosql_test.go index 2974e0dd0458..50908a93503b 100644 --- a/internal/tools/trino/trinosql/trinosql_test.go +++ b/internal/tools/trino/trinosql/trinosql_test.go @@ -17,7 +17,6 @@ package trinosql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlTrino(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: trino-sql - source: my-trino-instance - description: some description - statement: | - SELECT * FROM catalog.schema.table WHERE id = ?; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: id - type: string - description: ID to filter by - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id + kind: tools + name: example_tool + type: trino-sql + source: my-trino-instance + description: some description + statement: | + SELECT * FROM catalog.schema.table WHERE id = ?; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: id + type: string + description: ID to filter by + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id `, want: server.ToolConfigs{ "example_tool": trinosql.Config{ Name: "example_tool", - Kind: "trino-sql", + Type: "trino-sql", Source: "my-trino-instance", Description: "some description", Statement: "SELECT * FROM catalog.schema.table WHERE id = ?;\n", @@ -77,15 +76,11 @@ func TestParseFromYamlTrino(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -105,47 +100,47 @@ func TestParseFromYamlWithTemplateParamsTrino(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: trino-sql - source: my-trino-instance - description: some description - statement: | - SELECT * FROM {{ .catalog }}.{{ .schema }}.{{ .tableName }} WHERE country = ?; - authRequired: - - my-google-auth-service - - other-auth-service - parameters: - - name: country - type: string - description: some description - authServices: - - name: my-google-auth-service - field: user_id - - name: other-auth-service - field: user_id - templateParameters: - - name: catalog - type: string - description: The catalog to query from. - - name: schema - type: string - description: The schema to query from. - - name: tableName - type: string - description: The table to select data from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: trino-sql + source: my-trino-instance + description: some description + statement: | + SELECT * FROM {{ .catalog }}.{{ .schema }}.{{ .tableName }} WHERE country = ?; + authRequired: + - my-google-auth-service + - other-auth-service + parameters: + - name: country + type: string + description: some description + authServices: + - name: my-google-auth-service + field: user_id + - name: other-auth-service + field: user_id + templateParameters: + - name: catalog + type: string + description: The catalog to query from. + - name: schema + type: string + description: The schema to query from. + - name: tableName + type: string + description: The table to select data from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": trinosql.Config{ Name: "example_tool", - Kind: "trino-sql", + Type: "trino-sql", Source: "my-trino-instance", Description: "some description", Statement: "SELECT * FROM {{ .catalog }}.{{ .schema }}.{{ .tableName }} WHERE country = ?;\n", @@ -167,15 +162,11 @@ func TestParseFromYamlWithTemplateParamsTrino(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/utility/wait/wait.go b/internal/tools/utility/wait/wait.go index a5724fdac904..77024098b953 100644 --- a/internal/tools/utility/wait/wait.go +++ b/internal/tools/utility/wait/wait.go @@ -26,11 +26,11 @@ import ( "github.com/googleapis/genai-toolbox/internal/util/parameters" ) -const kind string = "wait" +const resourceType string = "wait" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -44,7 +44,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Description string `yaml:"description" validate:"required"` Timeout string `yaml:"timeout" validate:"required"` AuthRequired []string `yaml:"authRequired"` @@ -52,8 +52,8 @@ type Config struct { var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(_ map[string]sources.Source) (tools.Tool, error) { @@ -131,3 +131,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/utility/wait/wait_test.go b/internal/tools/utility/wait/wait_test.go index fcd060ac6b5c..fb3db875cd8b 100644 --- a/internal/tools/utility/wait/wait_test.go +++ b/internal/tools/utility/wait/wait_test.go @@ -17,7 +17,6 @@ package wait_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,18 +37,18 @@ func TestParseFromYamlWait(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: wait - description: some description - timeout: 10s - authRequired: - - my-google-auth-service + kind: tools + name: example_tool + type: wait + description: some description + timeout: 10s + authRequired: + - my-google-auth-service `, want: server.ToolConfigs{ "example_tool": wait.Config{ Name: "example_tool", - Kind: "wait", + Type: "wait", Description: "some description", Timeout: "10s", AuthRequired: []string{"my-google-auth-service"}, @@ -59,15 +58,11 @@ func TestParseFromYamlWait(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/valkey/valkey.go b/internal/tools/valkey/valkey.go index 6d3a8effc100..14b54d15dd27 100644 --- a/internal/tools/valkey/valkey.go +++ b/internal/tools/valkey/valkey.go @@ -25,11 +25,11 @@ import ( "github.com/valkey-io/valkey-go" ) -const kind string = "valkey" +const resourceType string = "valkey" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -48,7 +48,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Commands [][]string `yaml:"commands" validate:"required"` @@ -59,8 +59,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -85,7 +85,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -163,3 +163,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/valkey/valkey_test.go b/internal/tools/valkey/valkey_test.go index 8b9947180689..2bafe4c3d188 100644 --- a/internal/tools/valkey/valkey_test.go +++ b/internal/tools/valkey/valkey_test.go @@ -17,7 +17,6 @@ package valkey_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,23 +37,23 @@ func TestParseFromYamlvalkey(t *testing.T) { { desc: "basic example", in: ` - tools: - valkey_tool: - kind: valkey - source: my-valkey-instance - description: some description - commands: - - [SET, greeting, "hello, {{.name}}"] - - [GET, id] - parameters: - - name: name - type: string - description: user name + kind: tools + name: valkey_tool + type: valkey + source: my-valkey-instance + description: some description + commands: + - [SET, greeting, "hello, {{.name}}"] + - [GET, id] + parameters: + - name: name + type: string + description: user name `, want: server.ToolConfigs{ "valkey_tool": valkey.Config{ Name: "valkey_tool", - Kind: "valkey", + Type: "valkey", Source: "my-valkey-instance", Description: "some description", AuthRequired: []string{}, @@ -68,15 +67,11 @@ func TestParseFromYamlvalkey(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/internal/tools/yugabytedbsql/yugabytedbsql.go b/internal/tools/yugabytedbsql/yugabytedbsql.go index 53e05dcc993f..48f9248f1507 100644 --- a/internal/tools/yugabytedbsql/yugabytedbsql.go +++ b/internal/tools/yugabytedbsql/yugabytedbsql.go @@ -26,11 +26,11 @@ import ( "github.com/yugabyte/pgx/v5/pgxpool" ) -const kind string = "yugabytedb-sql" +const resourceType string = "yugabytedb-sql" func init() { - if !tools.Register(kind, newConfig) { - panic(fmt.Sprintf("tool kind %q already registered", kind)) + if !tools.Register(resourceType, newConfig) { + panic(fmt.Sprintf("tool type %q already registered", resourceType)) } } @@ -49,7 +49,7 @@ type compatibleSource interface { type Config struct { Name string `yaml:"name" validate:"required"` - Kind string `yaml:"kind" validate:"required"` + Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Description string `yaml:"description" validate:"required"` Statement string `yaml:"statement" validate:"required"` @@ -61,8 +61,8 @@ type Config struct { // validate interface var _ tools.ToolConfig = Config{} -func (cfg Config) ToolConfigKind() string { - return kind +func (cfg Config) ToolConfigType() string { + return resourceType } func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) { @@ -94,7 +94,7 @@ type Tool struct { } func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) { - source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Kind) + source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type) if err != nil { return nil, err } @@ -144,3 +144,7 @@ func (t Tool) ToConfig() tools.ToolConfig { func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) { return "Authorization", nil } + +func (t Tool) GetParameters() parameters.Parameters { + return t.Parameters +} diff --git a/internal/tools/yugabytedbsql/yugabytedbsql_test.go b/internal/tools/yugabytedbsql/yugabytedbsql_test.go index e0a9cd1d0497..24ff00015377 100644 --- a/internal/tools/yugabytedbsql/yugabytedbsql_test.go +++ b/internal/tools/yugabytedbsql/yugabytedbsql_test.go @@ -17,7 +17,6 @@ package yugabytedbsql_test import ( "testing" - yaml "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/testutils" @@ -38,30 +37,30 @@ func TestParseFromYamlYugabyteDBSQL(t *testing.T) { { desc: "basic valid config", in: ` - tools: - hotel_search: - kind: yugabytedb-sql - source: yb-source - description: search hotels by city - statement: | - SELECT * FROM hotels WHERE city = $1; - authRequired: - - auth-service-a - - auth-service-b - parameters: - - name: city - type: string - description: city name - authServices: - - name: auth-service-a - field: user_id - - name: auth-service-b - field: user_id + kind: tools + name: hotel_search + type: yugabytedb-sql + source: yb-source + description: search hotels by city + statement: | + SELECT * FROM hotels WHERE city = $1; + authRequired: + - auth-service-a + - auth-service-b + parameters: + - name: city + type: string + description: city name + authServices: + - name: auth-service-a + field: user_id + - name: auth-service-b + field: user_id `, want: server.ToolConfigs{ "hotel_search": yugabytedbsql.Config{ Name: "hotel_search", - Kind: "yugabytedb-sql", + Type: "yugabytedb-sql", Source: "yb-source", Description: "search hotels by city", Statement: "SELECT * FROM hotels WHERE city = $1;\n", @@ -81,14 +80,11 @@ func TestParseFromYamlYugabyteDBSQL(t *testing.T) { for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) @@ -107,32 +103,29 @@ func TestFailParseFromYamlYugabyteDBSQL(t *testing.T) { { desc: "missing required field (statement)", in: ` - tools: - tool1: - kind: yugabytedb-sql - source: yb-source - description: incomplete config + kind: tools + name: tool1 + type: yugabytedb-sql + source: yb-source + description: incomplete config `, }, { desc: "unknown field (foo)", in: ` - tools: - tool2: - kind: yugabytedb-sql - source: yb-source - description: test - statement: SELECT 1; - foo: bar + kind: tools + name: tool2 + type: yugabytedb-sql + source: yb-source + description: test + statement: SELECT 1; + foo: bar `, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - cfg := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &cfg) + _, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err == nil { t.Fatalf("expected error but got none") } @@ -153,33 +146,33 @@ func TestParseFromYamlWithTemplateParamsYugabyteDB(t *testing.T) { { desc: "basic example", in: ` - tools: - example_tool: - kind: yugabytedb-sql - source: my-yb-instance - description: some description - statement: | - SELECT * FROM SQL_STATEMENT; - parameters: - - name: name - type: string - description: some description - templateParameters: - - name: tableName - type: string - description: The table to select hotels from. - - name: fieldArray - type: array - description: The columns to return for the query. - items: - name: column - type: string - description: A column name that will be returned from the query. + kind: tools + name: example_tool + type: yugabytedb-sql + source: my-yb-instance + description: some description + statement: | + SELECT * FROM SQL_STATEMENT; + parameters: + - name: name + type: string + description: some description + templateParameters: + - name: tableName + type: string + description: The table to select hotels from. + - name: fieldArray + type: array + description: The columns to return for the query. + items: + name: column + type: string + description: A column name that will be returned from the query. `, want: server.ToolConfigs{ "example_tool": yugabytedbsql.Config{ Name: "example_tool", - Kind: "yugabytedb-sql", + Type: "yugabytedb-sql", Source: "my-yb-instance", Description: "some description", Statement: "SELECT * FROM SQL_STATEMENT;\n", @@ -197,15 +190,11 @@ func TestParseFromYamlWithTemplateParamsYugabyteDB(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Tools server.ToolConfigs `yaml:"tools"` - }{} - // Parse contents - err := yaml.UnmarshalContext(ctx, testutils.FormatYaml(tc.in), &got) + _, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if diff := cmp.Diff(tc.want, got.Tools); diff != "" { + if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("incorrect parse: diff %v", diff) } }) diff --git a/tests/alloydb/alloydb_integration_test.go b/tests/alloydb/alloydb_integration_test.go index 0c2c3bb2e216..52ad7731f310 100644 --- a/tests/alloydb/alloydb_integration_test.go +++ b/tests/alloydb/alloydb_integration_test.go @@ -74,71 +74,71 @@ func getAlloyDBToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "alloydb-admin-source": map[string]any{ - "kind": "alloydb-admin", + "type": "alloydb-admin", }, }, "tools": map[string]any{ // Tool for RunAlloyDBToolGetTest "my-simple-tool": map[string]any{ - "kind": "alloydb-list-clusters", + "type": "alloydb-list-clusters", "source": "alloydb-admin-source", "description": "Simple tool to test end to end functionality.", }, // Tool for MCP test "my-param-tool": map[string]any{ - "kind": "alloydb-list-clusters", + "type": "alloydb-list-clusters", "source": "alloydb-admin-source", "description": "Tool to list clusters", }, // Tool for MCP test that fails "my-fail-tool": map[string]any{ - "kind": "alloydb-list-clusters", + "type": "alloydb-list-clusters", "source": "alloydb-admin-source", "description": "Tool that will fail", }, // AlloyDB specific tools "alloydb-list-clusters": map[string]any{ - "kind": "alloydb-list-clusters", + "type": "alloydb-list-clusters", "source": "alloydb-admin-source", "description": "Lists all AlloyDB clusters in a given project and location.", }, "alloydb-list-users": map[string]any{ - "kind": "alloydb-list-users", + "type": "alloydb-list-users", "source": "alloydb-admin-source", "description": "Lists all AlloyDB users within a specific cluster.", }, "alloydb-list-instances": map[string]any{ - "kind": "alloydb-list-instances", + "type": "alloydb-list-instances", "source": "alloydb-admin-source", "description": "Lists all AlloyDB instances within a specific cluster.", }, "alloydb-get-cluster": map[string]any{ - "kind": "alloydb-get-cluster", + "type": "alloydb-get-cluster", "source": "alloydb-admin-source", "description": "Retrieves details of a specific AlloyDB cluster.", }, "alloydb-get-instance": map[string]any{ - "kind": "alloydb-get-instance", + "type": "alloydb-get-instance", "source": "alloydb-admin-source", "description": "Retrieves details of a specific AlloyDB instance.", }, "alloydb-get-user": map[string]any{ - "kind": "alloydb-get-user", + "type": "alloydb-get-user", "source": "alloydb-admin-source", "description": "Retrieves details of a specific AlloyDB user.", }, "alloydb-create-cluster": map[string]any{ - "kind": "alloydb-create-cluster", + "type": "alloydb-create-cluster", "description": "create cluster", "source": "alloydb-admin-source", }, "alloydb-create-instance": map[string]any{ - "kind": "alloydb-create-instance", + "type": "alloydb-create-instance", "description": "create instance", "source": "alloydb-admin-source", }, "alloydb-create-user": map[string]any{ - "kind": "alloydb-create-user", + "type": "alloydb-create-user", "description": "create user", "source": "alloydb-admin-source", }, diff --git a/tests/alloydb/alloydb_wait_for_operation_test.go b/tests/alloydb/alloydb_wait_for_operation_test.go index 1f027f556865..38dece22d01f 100644 --- a/tests/alloydb/alloydb_wait_for_operation_test.go +++ b/tests/alloydb/alloydb_wait_for_operation_test.go @@ -37,7 +37,7 @@ import ( ) var ( - waitToolKind = "alloydb-wait-for-operation" + waitToolType = "alloydb-wait-for-operation" ) type waitForOperationTransport struct { @@ -240,17 +240,17 @@ func getWaitToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-alloydb-source": map[string]any{ - "kind": "alloydb-admin", + "type": "alloydb-admin", }, }, "tools": map[string]any{ "wait-for-op1": map[string]any{ - "kind": waitToolKind, + "type": waitToolType, "source": "my-alloydb-source", "description": "wait for op1", }, "wait-for-op2": map[string]any{ - "kind": waitToolKind, + "type": waitToolType, "source": "my-alloydb-source", "description": "wait for op2", }, diff --git a/tests/alloydbainl/alloydb_ai_nl_integration_test.go b/tests/alloydbainl/alloydb_ai_nl_integration_test.go index 4c8754fdf4d0..1756eeb3f018 100644 --- a/tests/alloydbainl/alloydb_ai_nl_integration_test.go +++ b/tests/alloydbainl/alloydb_ai_nl_integration_test.go @@ -33,8 +33,8 @@ import ( ) var ( - AlloyDBAINLSourceKind = "alloydb-postgres" - AlloyDBAINLToolKind = "alloydb-ai-nl" + AlloyDBAINLSourceType = "alloydb-postgres" + AlloyDBAINLToolType = "alloydb-ai-nl" AlloyDBAINLProject = os.Getenv("ALLOYDB_AI_NL_PROJECT") AlloyDBAINLRegion = os.Getenv("ALLOYDB_AI_NL_REGION") AlloyDBAINLCluster = os.Getenv("ALLOYDB_AI_NL_CLUSTER") @@ -62,7 +62,7 @@ func getAlloyDBAINLVars(t *testing.T) map[string]any { t.Fatal("'ALLOYDB_AI_NL_PASS' not set") } return map[string]any{ - "kind": AlloyDBAINLSourceKind, + "type": AlloyDBAINLSourceType, "project": AlloyDBAINLProject, "cluster": AlloyDBAINLCluster, "instance": AlloyDBAINLInstance, @@ -285,19 +285,19 @@ func getAINLToolsConfig(sourceConfig map[string]any) map[string]any { }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": AlloyDBAINLToolKind, + "type": AlloyDBAINLToolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "nlConfig": "my_nl_config", }, "my-auth-tool": map[string]any{ - "kind": AlloyDBAINLToolKind, + "type": AlloyDBAINLToolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", "nlConfig": "my_nl_config", @@ -316,7 +316,7 @@ func getAINLToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-required-tool": map[string]any{ - "kind": AlloyDBAINLToolKind, + "type": AlloyDBAINLToolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "nlConfig": "my_nl_config", diff --git a/tests/alloydbpg/alloydb_pg_integration_test.go b/tests/alloydbpg/alloydb_pg_integration_test.go index 32463f1ea09b..92542567907c 100644 --- a/tests/alloydbpg/alloydb_pg_integration_test.go +++ b/tests/alloydbpg/alloydb_pg_integration_test.go @@ -32,8 +32,8 @@ import ( ) var ( - AlloyDBPostgresSourceKind = "alloydb-postgres" - AlloyDBPostgresToolKind = "postgres-sql" + AlloyDBPostgresSourceType = "alloydb-postgres" + AlloyDBPostgresToolType = "postgres-sql" AlloyDBPostgresProject = os.Getenv("ALLOYDB_POSTGRES_PROJECT") AlloyDBPostgresRegion = os.Getenv("ALLOYDB_POSTGRES_REGION") AlloyDBPostgresCluster = os.Getenv("ALLOYDB_POSTGRES_CLUSTER") @@ -61,7 +61,7 @@ func getAlloyDBPgVars(t *testing.T) map[string]any { t.Fatal("'ALLOYDB_POSTGRES_PASS' not set") } return map[string]any{ - "kind": AlloyDBPostgresSourceKind, + "type": AlloyDBPostgresSourceType, "project": AlloyDBPostgresProject, "cluster": AlloyDBPostgresCluster, "instance": AlloyDBPostgresInstance, @@ -152,14 +152,14 @@ func TestAlloyDBPgToolEndpoints(t *testing.T) { defer tearDownVectorTable(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, AlloyDBPostgresToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, AlloyDBPostgresToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddExecuteSqlConfig(t, toolsFile, "postgres-execute-sql") tmplSelectCombined, tmplSelectFilterCombined := tests.GetPostgresSQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, AlloyDBPostgresToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, AlloyDBPostgresToolType, tmplSelectCombined, tmplSelectFilterCombined, "") // Add semantic search tool config insertStmt, searchStmt := tests.GetPostgresVectorSearchStmts(vectorTableName) - toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, AlloyDBPostgresToolKind, insertStmt, searchStmt) + toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, AlloyDBPostgresToolType, insertStmt, searchStmt) toolsFile = tests.AddPostgresPrebuiltConfig(t, toolsFile) @@ -232,7 +232,7 @@ func TestAlloyDBPgIpConnection(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { sourceConfig["ipType"] = tc.ipType - err := tests.RunSourceConnectionTest(t, sourceConfig, AlloyDBPostgresToolKind) + err := tests.RunSourceConnectionTest(t, sourceConfig, AlloyDBPostgresToolType) if err != nil { t.Fatalf("Connection test failure: %s", err) } @@ -247,7 +247,7 @@ func TestAlloyDBPgIAMConnection(t *testing.T) { serviceAccountEmail := strings.TrimSuffix(tests.ServiceAccountEmail, ".gserviceaccount.com") noPassSourceConfig := map[string]any{ - "kind": AlloyDBPostgresSourceKind, + "type": AlloyDBPostgresSourceType, "project": AlloyDBPostgresProject, "cluster": AlloyDBPostgresCluster, "instance": AlloyDBPostgresInstance, @@ -257,7 +257,7 @@ func TestAlloyDBPgIAMConnection(t *testing.T) { } noUserSourceConfig := map[string]any{ - "kind": AlloyDBPostgresSourceKind, + "type": AlloyDBPostgresSourceType, "project": AlloyDBPostgresProject, "cluster": AlloyDBPostgresCluster, "instance": AlloyDBPostgresInstance, @@ -267,7 +267,7 @@ func TestAlloyDBPgIAMConnection(t *testing.T) { } noUserNoPassSourceConfig := map[string]any{ - "kind": AlloyDBPostgresSourceKind, + "type": AlloyDBPostgresSourceType, "project": AlloyDBPostgresProject, "cluster": AlloyDBPostgresCluster, "instance": AlloyDBPostgresInstance, @@ -297,7 +297,7 @@ func TestAlloyDBPgIAMConnection(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - err := tests.RunSourceConnectionTest(t, tc.sourceConfig, AlloyDBPostgresToolKind) + err := tests.RunSourceConnectionTest(t, tc.sourceConfig, AlloyDBPostgresToolType) if err != nil { if tc.isErr { return diff --git a/tests/bigquery/bigquery_integration_test.go b/tests/bigquery/bigquery_integration_test.go index de5126cd2410..6059c190a8d8 100644 --- a/tests/bigquery/bigquery_integration_test.go +++ b/tests/bigquery/bigquery_integration_test.go @@ -41,8 +41,8 @@ import ( ) var ( - BigquerySourceKind = "bigquery" - BigqueryToolKind = "bigquery-sql" + BigquerySourceType = "bigquery" + BigqueryToolType = "bigquery-sql" BigqueryProject = os.Getenv("BIGQUERY_PROJECT") ) @@ -53,7 +53,7 @@ func getBigQueryVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": BigquerySourceKind, + "type": BigquerySourceType, "project": BigqueryProject, } } @@ -146,12 +146,12 @@ func TestBigQueryToolEndpoints(t *testing.T) { defer teardownTable5(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, BigqueryToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, BigqueryToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addClientAuthSourceConfig(t, toolsFile) toolsFile = addBigQuerySqlToolConfig(t, toolsFile, dataTypeToolStmt, arrayDataTypeToolStmt) toolsFile = addBigQueryPrebuiltToolsConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getBigQueryTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, BigqueryToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, BigqueryToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -286,42 +286,42 @@ func TestBigQueryToolWithDatasetRestriction(t *testing.T) { // Configure tool toolsConfig := map[string]any{ "list-dataset-ids-restricted": map[string]any{ - "kind": "bigquery-list-dataset-ids", + "type": "bigquery-list-dataset-ids", "source": "my-instance", "description": "Tool to list dataset ids", }, "list-table-ids-restricted": map[string]any{ - "kind": "bigquery-list-table-ids", + "type": "bigquery-list-table-ids", "source": "my-instance", "description": "Tool to list table within a dataset", }, "get-dataset-info-restricted": map[string]any{ - "kind": "bigquery-get-dataset-info", + "type": "bigquery-get-dataset-info", "source": "my-instance", "description": "Tool to get dataset info", }, "get-table-info-restricted": map[string]any{ - "kind": "bigquery-get-table-info", + "type": "bigquery-get-table-info", "source": "my-instance", "description": "Tool to get table info", }, "execute-sql-restricted": map[string]any{ - "kind": "bigquery-execute-sql", + "type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute SQL", }, "conversational-analytics-restricted": map[string]any{ - "kind": "bigquery-conversational-analytics", + "type": "bigquery-conversational-analytics", "source": "my-instance", "description": "Tool to ask BigQuery conversational analytics", }, "forecast-restricted": map[string]any{ - "kind": "bigquery-forecast", + "type": "bigquery-forecast", "source": "my-instance", "description": "Tool to forecast", }, "analyze-contribution-restricted": map[string]any{ - "kind": "bigquery-analyze-contribution", + "type": "bigquery-analyze-contribution", "source": "my-instance", "description": "Tool to analyze contribution", }, @@ -398,7 +398,7 @@ func TestBigQueryWriteModeAllowed(t *testing.T) { }, "tools": map[string]any{ "my-exec-sql-tool": map[string]any{ - "kind": "bigquery-execute-sql", + "type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql", }, @@ -444,7 +444,7 @@ func TestBigQueryWriteModeBlocked(t *testing.T) { toolsFile := map[string]any{ "sources": map[string]any{"my-instance": sourceConfig}, "tools": map[string]any{ - "my-exec-sql-tool": map[string]any{"kind": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql"}, + "my-exec-sql-tool": map[string]any{"type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql"}, }, } @@ -490,20 +490,20 @@ func TestBigQueryWriteModeProtected(t *testing.T) { toolsFile := map[string]any{ "sources": map[string]any{"my-instance": sourceConfig}, "tools": map[string]any{ - "my-exec-sql-tool": map[string]any{"kind": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql"}, + "my-exec-sql-tool": map[string]any{"type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql"}, "my-sql-tool-protected": map[string]any{ - "kind": "bigquery-sql", + "type": "bigquery-sql", "source": "my-instance", "description": "Tool to query from the session", "statement": "SELECT * FROM my_shared_temp_table", }, "my-forecast-tool-protected": map[string]any{ - "kind": "bigquery-forecast", + "type": "bigquery-forecast", "source": "my-instance", "description": "Tool to forecast from session temp table", }, "my-analyze-contribution-tool-protected": map[string]any{ - "kind": "bigquery-analyze-contribution", + "type": "bigquery-analyze-contribution", "source": "my-instance", "description": "Tool to analyze contribution from session temp table", }, @@ -527,7 +527,7 @@ func TestBigQueryWriteModeProtected(t *testing.T) { runBigQueryWriteModeProtectedTest(t, permanentDatasetName) } -// getBigQueryParamToolInfo returns statements and param for my-tool for bigquery kind +// getBigQueryParamToolInfo returns statements and param for my-tool for bigquery type func getBigQueryParamToolInfo(tableName string) (string, string, string, string, string, string, []bigqueryapi.QueryParameter) { createStatement := fmt.Sprintf(` CREATE TABLE IF NOT EXISTS %s (id INT64, name STRING);`, tableName) @@ -546,7 +546,7 @@ func getBigQueryParamToolInfo(tableName string) (string, string, string, string, return createStatement, insertStatement, toolStatement, idToolStatement, nameToolStatement, arrayToolStatememt, params } -// getBigQueryAuthToolInfo returns statements and param of my-auth-tool for bigquery kind +// getBigQueryAuthToolInfo returns statements and param of my-auth-tool for bigquery type func getBigQueryAuthToolInfo(tableName string) (string, string, string, []bigqueryapi.QueryParameter) { createStatement := fmt.Sprintf(` CREATE TABLE IF NOT EXISTS %s (id INT64, name STRING, email STRING)`, tableName) @@ -616,7 +616,7 @@ func getBigQueryAnalyzeContributionToolInfo(tableName string) (string, string, [ return createStatement, insertStatement, params } -// getBigQueryTmplToolStatement returns statements for template parameter test cases for bigquery kind +// getBigQueryTmplToolStatement returns statements for template parameter test cases for bigquery type func getBigQueryTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ? ORDER BY id" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ? ORDER BY id" @@ -708,12 +708,12 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "bigquery-execute-sql", + "type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "bigquery-execute-sql", + "type": "bigquery-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -721,17 +721,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-exec-sql-tool"] = map[string]any{ - "kind": "bigquery-execute-sql", + "type": "bigquery-execute-sql", "source": "my-client-auth-source", "description": "Tool to execute sql", } tools["my-forecast-tool"] = map[string]any{ - "kind": "bigquery-forecast", + "type": "bigquery-forecast", "source": "my-instance", "description": "Tool to forecast time series data.", } tools["my-auth-forecast-tool"] = map[string]any{ - "kind": "bigquery-forecast", + "type": "bigquery-forecast", "source": "my-instance", "description": "Tool to forecast time series data with auth.", "authRequired": []string{ @@ -739,17 +739,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-forecast-tool"] = map[string]any{ - "kind": "bigquery-forecast", + "type": "bigquery-forecast", "source": "my-client-auth-source", "description": "Tool to forecast time series data with auth.", } tools["my-analyze-contribution-tool"] = map[string]any{ - "kind": "bigquery-analyze-contribution", + "type": "bigquery-analyze-contribution", "source": "my-instance", "description": "Tool to analyze contribution.", } tools["my-auth-analyze-contribution-tool"] = map[string]any{ - "kind": "bigquery-analyze-contribution", + "type": "bigquery-analyze-contribution", "source": "my-instance", "description": "Tool to analyze contribution with auth.", "authRequired": []string{ @@ -757,17 +757,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-analyze-contribution-tool"] = map[string]any{ - "kind": "bigquery-analyze-contribution", + "type": "bigquery-analyze-contribution", "source": "my-client-auth-source", "description": "Tool to analyze contribution with auth.", } tools["my-list-dataset-ids-tool"] = map[string]any{ - "kind": "bigquery-list-dataset-ids", + "type": "bigquery-list-dataset-ids", "source": "my-instance", "description": "Tool to list dataset", } tools["my-auth-list-dataset-ids-tool"] = map[string]any{ - "kind": "bigquery-list-dataset-ids", + "type": "bigquery-list-dataset-ids", "source": "my-instance", "description": "Tool to list dataset", "authRequired": []string{ @@ -775,17 +775,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-list-dataset-ids-tool"] = map[string]any{ - "kind": "bigquery-list-dataset-ids", + "type": "bigquery-list-dataset-ids", "source": "my-client-auth-source", "description": "Tool to list dataset", } tools["my-get-dataset-info-tool"] = map[string]any{ - "kind": "bigquery-get-dataset-info", + "type": "bigquery-get-dataset-info", "source": "my-instance", "description": "Tool to show dataset metadata", } tools["my-auth-get-dataset-info-tool"] = map[string]any{ - "kind": "bigquery-get-dataset-info", + "type": "bigquery-get-dataset-info", "source": "my-instance", "description": "Tool to show dataset metadata", "authRequired": []string{ @@ -793,17 +793,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-get-dataset-info-tool"] = map[string]any{ - "kind": "bigquery-get-dataset-info", + "type": "bigquery-get-dataset-info", "source": "my-client-auth-source", "description": "Tool to show dataset metadata", } tools["my-list-table-ids-tool"] = map[string]any{ - "kind": "bigquery-list-table-ids", + "type": "bigquery-list-table-ids", "source": "my-instance", "description": "Tool to list table within a dataset", } tools["my-auth-list-table-ids-tool"] = map[string]any{ - "kind": "bigquery-list-table-ids", + "type": "bigquery-list-table-ids", "source": "my-instance", "description": "Tool to list table within a dataset", "authRequired": []string{ @@ -811,17 +811,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-list-table-ids-tool"] = map[string]any{ - "kind": "bigquery-list-table-ids", + "type": "bigquery-list-table-ids", "source": "my-client-auth-source", "description": "Tool to list table within a dataset", } tools["my-get-table-info-tool"] = map[string]any{ - "kind": "bigquery-get-table-info", + "type": "bigquery-get-table-info", "source": "my-instance", "description": "Tool to show dataset metadata", } tools["my-auth-get-table-info-tool"] = map[string]any{ - "kind": "bigquery-get-table-info", + "type": "bigquery-get-table-info", "source": "my-instance", "description": "Tool to show dataset metadata", "authRequired": []string{ @@ -829,17 +829,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-get-table-info-tool"] = map[string]any{ - "kind": "bigquery-get-table-info", + "type": "bigquery-get-table-info", "source": "my-client-auth-source", "description": "Tool to show dataset metadata", } tools["my-conversational-analytics-tool"] = map[string]any{ - "kind": "bigquery-conversational-analytics", + "type": "bigquery-conversational-analytics", "source": "my-instance", "description": "Tool to ask BigQuery conversational analytics", } tools["my-auth-conversational-analytics-tool"] = map[string]any{ - "kind": "bigquery-conversational-analytics", + "type": "bigquery-conversational-analytics", "source": "my-instance", "description": "Tool to ask BigQuery conversational analytics", "authRequired": []string{ @@ -847,17 +847,17 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-conversational-analytics-tool"] = map[string]any{ - "kind": "bigquery-conversational-analytics", + "type": "bigquery-conversational-analytics", "source": "my-client-auth-source", "description": "Tool to ask BigQuery conversational analytics", } tools["my-search-catalog-tool"] = map[string]any{ - "kind": "bigquery-search-catalog", + "type": "bigquery-search-catalog", "source": "my-instance", "description": "Tool to search the BiqQuery catalog", } tools["my-auth-search-catalog-tool"] = map[string]any{ - "kind": "bigquery-search-catalog", + "type": "bigquery-search-catalog", "source": "my-instance", "description": "Tool to search the BiqQuery catalog", "authRequired": []string{ @@ -865,7 +865,7 @@ func addBigQueryPrebuiltToolsConfig(t *testing.T, config map[string]any) map[str }, } tools["my-client-auth-search-catalog-tool"] = map[string]any{ - "kind": "bigquery-search-catalog", + "type": "bigquery-search-catalog", "source": "my-client-auth-source", "description": "Tool to search the BiqQuery catalog", } @@ -879,7 +879,7 @@ func addClientAuthSourceConfig(t *testing.T, config map[string]any) map[string]a t.Fatalf("unable to get sources from config") } sources["my-client-auth-source"] = map[string]any{ - "kind": BigquerySourceKind, + "type": BigquerySourceType, "project": BigqueryProject, "useClientOAuth": true, } @@ -893,7 +893,7 @@ func addBigQuerySqlToolConfig(t *testing.T, config map[string]any, toolStatement t.Fatalf("unable to get tools from config") } tools["my-scalar-datatype-tool"] = map[string]any{ - "kind": "bigquery-sql", + "type": "bigquery-sql", "source": "my-instance", "description": "Tool to test various scalar data types.", "statement": toolStatement, @@ -905,7 +905,7 @@ func addBigQuerySqlToolConfig(t *testing.T, config map[string]any, toolStatement }, } tools["my-array-datatype-tool"] = map[string]any{ - "kind": "bigquery-sql", + "type": "bigquery-sql", "source": "my-instance", "description": "Tool to test various array data types.", "statement": arrayToolStatement, @@ -917,7 +917,7 @@ func addBigQuerySqlToolConfig(t *testing.T, config map[string]any, toolStatement }, } tools["my-client-auth-tool"] = map[string]any{ - "kind": "bigquery-sql", + "type": "bigquery-sql", "source": "my-client-auth-source", "description": "Tool to test client authorization.", "statement": "SELECT 1", diff --git a/tests/bigtable/bigtable_integration_test.go b/tests/bigtable/bigtable_integration_test.go index 12246cf398fa..49a7ca69c3d4 100644 --- a/tests/bigtable/bigtable_integration_test.go +++ b/tests/bigtable/bigtable_integration_test.go @@ -35,8 +35,8 @@ import ( ) var ( - BigtableSourceKind = "bigtable" - BigtableToolKind = "bigtable-sql" + BigtableSourceType = "bigtable" + BigtableToolType = "bigtable-sql" BigtableProject = os.Getenv("BIGTABLE_PROJECT") BigtableInstance = os.Getenv("BIGTABLE_INSTANCE") ) @@ -50,7 +50,7 @@ func getBigtableVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": BigtableSourceKind, + "type": BigtableSourceType, "project": BigtableProject, "instance": BigtableInstance, } @@ -99,7 +99,7 @@ func TestBigtableToolEndpoints(t *testing.T) { defer teardownTableTmpl(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, BigtableToolKind, paramTestStatement, idParamTestStatement, nameParamTestStatement, arrayTestStatement, authToolStatement) + toolsFile := tests.GetToolsConfig(sourceConfig, BigtableToolType, paramTestStatement, idParamTestStatement, nameParamTestStatement, arrayTestStatement, authToolStatement) toolsFile = addTemplateParamConfig(t, toolsFile) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) @@ -291,7 +291,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any t.Fatalf("unable to get tools from config") } toolsMap["select-templateParams-tool"] = map[string]any{ - "kind": "bigtable-sql", + "type": "bigtable-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT TO_INT64(cf['age']) as age, TO_INT64(cf['id']) as id, CAST(cf['name'] AS string) as name, FROM {{.tableName}};", @@ -300,7 +300,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-templateParams-combined-tool"] = map[string]any{ - "kind": "bigtable-sql", + "type": "bigtable-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT TO_INT64(cf['age']) as age, TO_INT64(cf['id']) as id, CAST(cf['name'] AS string) as name, FROM {{.tableName}} WHERE TO_INT64(cf['id']) = @id;", @@ -310,7 +310,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-fields-templateParams-tool"] = map[string]any{ - "kind": "bigtable-sql", + "type": "bigtable-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT {{array .fields}}, FROM {{.tableName}};", @@ -320,7 +320,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-filter-templateParams-combined-tool"] = map[string]any{ - "kind": "bigtable-sql", + "type": "bigtable-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT TO_INT64(cf['age']) as age, TO_INT64(cf['id']) as id, CAST(cf['name'] AS string) as name, FROM {{.tableName}} WHERE {{.columnFilter}} = @name;", diff --git a/tests/cassandra/cassandra_integration_test.go b/tests/cassandra/cassandra_integration_test.go index 21d41beb5f29..e1faac4554e8 100644 --- a/tests/cassandra/cassandra_integration_test.go +++ b/tests/cassandra/cassandra_integration_test.go @@ -31,8 +31,8 @@ import ( ) var ( - CassandraSourceKind = "cassandra" - CassandraToolKind = "cassandra-cql" + CassandraSourceType = "cassandra" + CassandraToolType = "cassandra-cql" Hosts = os.Getenv("CASSANDRA_HOST") Keyspace = "example_keyspace" Username = os.Getenv("CASSANDRA_USER") @@ -49,7 +49,7 @@ func getCassandraVars(t *testing.T) map[string]any { t.Fatal("'Password' not set") } return map[string]any{ - "kind": CassandraSourceKind, + "type": CassandraSourceType, "hosts": strings.Split(Hosts, ","), "keyspace": Keyspace, "username": Username, @@ -204,12 +204,12 @@ func TestCassandra(t *testing.T) { paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt := createParamToolInfo(paramTableName) _, _, authToolStmt := getCassandraAuthToolInfo(tableNameAuth) - toolsFile := tests.GetToolsConfig(sourceConfig, CassandraToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, CassandraToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) tmplSelectCombined, tmplSelectFilterCombined := getCassandraTmplToolInfo() tmpSelectAll := "SELECT * FROM {{.tableName}} where id = 1" - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CassandraToolKind, tmplSelectCombined, tmplSelectFilterCombined, tmpSelectAll) + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CassandraToolType, tmplSelectCombined, tmplSelectFilterCombined, tmpSelectAll) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/clickhouse/clickhouse_integration_test.go b/tests/clickhouse/clickhouse_integration_test.go index 058e4d1b1ace..911bfdde1116 100644 --- a/tests/clickhouse/clickhouse_integration_test.go +++ b/tests/clickhouse/clickhouse_integration_test.go @@ -35,8 +35,8 @@ import ( ) var ( - ClickHouseSourceKind = "clickhouse" - ClickHouseToolKind = "clickhouse-sql" + ClickHouseSourceType = "clickhouse" + ClickHouseToolType = "clickhouse-sql" ClickHouseDatabase = os.Getenv("CLICKHOUSE_DATABASE") ClickHouseHost = os.Getenv("CLICKHOUSE_HOST") ClickHousePort = os.Getenv("CLICKHOUSE_PORT") @@ -64,7 +64,7 @@ func getClickHouseVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": ClickHouseSourceKind, + "type": ClickHouseSourceType, "host": ClickHouseHost, "port": ClickHousePort, "database": ClickHouseDatabase, @@ -126,10 +126,10 @@ func TestClickHouse(t *testing.T) { teardownTable2 := setupClickHouseSQLTable(t, ctx, pool, createAuthTableStmt, insertAuthTableStmt, tableNameAuth, authTestParams) defer teardownTable2(t) - toolsFile := tests.GetToolsConfig(sourceConfig, ClickHouseToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, ClickHouseToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addClickHouseExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getClickHouseSQLTmplToolStatement() - toolsFile = addClickHouseTemplateParamConfig(t, toolsFile, ClickHouseToolKind, tmplSelectCombined, tmplSelectFilterCombined) + toolsFile = addClickHouseTemplateParamConfig(t, toolsFile, ClickHouseToolType, tmplSelectCombined, tmplSelectFilterCombined) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -162,12 +162,12 @@ func addClickHouseExecuteSqlConfig(t *testing.T, config map[string]any) map[stri t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "clickhouse-execute-sql", + "type": "clickhouse-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "clickhouse-execute-sql", + "type": "clickhouse-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -178,7 +178,7 @@ func addClickHouseExecuteSqlConfig(t *testing.T, config map[string]any) map[stri return config } -func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplSelectCombined, tmplSelectFilterCombined string) map[string]any { +func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolType, tmplSelectCombined, tmplSelectFilterCombined string) map[string]any { toolsMap, ok := config["tools"].(map[string]any) if !ok { t.Fatalf("unable to get tools from config") @@ -186,7 +186,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK // ClickHouse-specific template parameter tools with compatible syntax toolsMap["create-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": "CREATE TABLE {{.tableName}} ({{array .columns}}) ORDER BY id", @@ -196,7 +196,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK }, } toolsMap["insert-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Insert table tool with template parameters", "statement": "INSERT INTO {{.tableName}} ({{array .columns}}) VALUES ({{.values}})", @@ -207,7 +207,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK }, } toolsMap["select-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with template parameters", "statement": "SELECT id AS \"id\", name AS \"name\", age AS \"age\" FROM {{.tableName}} ORDER BY id", @@ -216,7 +216,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK }, } toolsMap["select-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with combined template parameters", "statement": tmplSelectCombined, @@ -228,7 +228,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK }, } toolsMap["select-fields-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select specific fields tool with template parameters", "statement": "SELECT name AS \"name\" FROM {{.tableName}} ORDER BY id", @@ -237,7 +237,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK }, } toolsMap["select-filter-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with filter template parameters", "statement": tmplSelectFilterCombined, @@ -251,7 +251,7 @@ func addClickHouseTemplateParamConfig(t *testing.T, config map[string]any, toolK } // Firebird uses simple DROP TABLE syntax without IF EXISTS toolsMap["drop-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Drop table tool with template parameters", "statement": "DROP TABLE {{.tableName}}", @@ -310,7 +310,7 @@ func TestClickHouseBasicConnection(t *testing.T) { }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": ClickHouseToolKind, + "type": ClickHouseToolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "statement": "SELECT 1;", @@ -386,13 +386,13 @@ func TestClickHouseSQLTool(t *testing.T) { }, "tools": map[string]any{ "test-select": map[string]any{ - "kind": ClickHouseToolKind, + "type": ClickHouseToolType, "source": "my-instance", "description": "Test select query", "statement": fmt.Sprintf("SELECT * FROM %s ORDER BY id", tableName), }, "test-param-query": map[string]any{ - "kind": ClickHouseToolKind, + "type": ClickHouseToolType, "source": "my-instance", "description": "Test parameterized query", "statement": fmt.Sprintf("SELECT * FROM %s WHERE age > ? ORDER BY id", tableName), @@ -401,7 +401,7 @@ func TestClickHouseSQLTool(t *testing.T) { }, }, "test-empty-result": map[string]any{ - "kind": ClickHouseToolKind, + "type": ClickHouseToolType, "source": "my-instance", "description": "Test query with no results", "statement": fmt.Sprintf("SELECT * FROM %s WHERE id = ?", tableName), @@ -410,7 +410,7 @@ func TestClickHouseSQLTool(t *testing.T) { }, }, "test-invalid-sql": map[string]any{ - "kind": ClickHouseToolKind, + "type": ClickHouseToolType, "source": "my-instance", "description": "Test invalid SQL", "statement": "SELEC * FROM nonexistent_table", // Typo in SELECT @@ -522,7 +522,7 @@ func TestClickHouseExecuteSQLTool(t *testing.T) { }, "tools": map[string]any{ "execute-sql-tool": map[string]any{ - "kind": "clickhouse-execute-sql", + "type": "clickhouse-execute-sql", "source": "my-instance", "description": "Test create table", }, @@ -640,18 +640,18 @@ func TestClickHouseEdgeCases(t *testing.T) { }, "tools": map[string]any{ "execute-sql-tool": map[string]any{ - "kind": "clickhouse-execute-sql", + "type": "clickhouse-execute-sql", "source": "my-instance", "description": "Test create table", }, "test-null-values": map[string]any{ - "kind": "clickhouse-sql", + "type": "clickhouse-sql", "source": "my-instance", "description": "Test null values", "statement": fmt.Sprintf("SELECT * FROM %s ORDER BY id", tableName), }, "test-concurrent": map[string]any{ - "kind": "clickhouse-sql", + "type": "clickhouse-sql", "source": "my-instance", "description": "Test concurrent queries", "statement": "SELECT number FROM system.numbers LIMIT ?", @@ -818,7 +818,7 @@ func TestClickHouseEdgeCases(t *testing.T) { t.Logf("âś… Edge case tests completed successfully") } -// getClickHouseSQLParamToolInfo returns statements and param for my-tool clickhouse-sql kind +// getClickHouseSQLParamToolInfo returns statements and param for my-tool clickhouse-sql type func getClickHouseSQLParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id UInt32, name String) ENGINE = Memory", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name) VALUES (?, ?), (?, ?), (?, ?), (?, ?)", tableName) @@ -830,7 +830,7 @@ func getClickHouseSQLParamToolInfo(tableName string) (string, string, string, st return createStatement, insertStatement, paramStatement, idParamStatement, nameParamStatement, arrayStatement, params } -// getClickHouseSQLAuthToolInfo returns statements and param of my-auth-tool for clickhouse-sql kind +// getClickHouseSQLAuthToolInfo returns statements and param of my-auth-tool for clickhouse-sql type func getClickHouseSQLAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id UInt32, name String, email String) ENGINE = Memory", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name, email) VALUES (?, ?, ?), (?, ?, ?)", tableName) @@ -839,7 +839,7 @@ func getClickHouseSQLAuthToolInfo(tableName string) (string, string, string, []a return createStatement, insertStatement, authStatement, params } -// getClickHouseSQLTmplToolStatement returns statements and param for template parameter test cases for clickhouse-sql kind +// getClickHouseSQLTmplToolStatement returns statements and param for template parameter test cases for clickhouse-sql type func getClickHouseSQLTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ?" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ?" @@ -902,12 +902,12 @@ func TestClickHouseListDatabasesTool(t *testing.T) { }, "tools": map[string]any{ "test-list-databases": map[string]any{ - "kind": "clickhouse-list-databases", + "type": "clickhouse-list-databases", "source": "my-instance", "description": "Test listing databases", }, "test-invalid-source": map[string]any{ - "kind": "clickhouse-list-databases", + "type": "clickhouse-list-databases", "source": "non-existent-source", "description": "Test with invalid source", }, @@ -1031,12 +1031,12 @@ func TestClickHouseListTablesTool(t *testing.T) { }, "tools": map[string]any{ "test-list-tables": map[string]any{ - "kind": "clickhouse-list-tables", + "type": "clickhouse-list-tables", "source": "my-instance", "description": "Test listing tables", }, "test-invalid-source": map[string]any{ - "kind": "clickhouse-list-tables", + "type": "clickhouse-list-tables", "source": "non-existent-source", "description": "Test with invalid source", }, diff --git a/tests/cloudgda/cloud_gda_integration_test.go b/tests/cloudgda/cloud_gda_integration_test.go index 343973f14729..24c0cab1cbe1 100644 --- a/tests/cloudgda/cloud_gda_integration_test.go +++ b/tests/cloudgda/cloud_gda_integration_test.go @@ -33,7 +33,7 @@ import ( ) var ( - cloudGdaToolKind = "cloud-gemini-data-analytics-query" + cloudGdaToolType = "cloud-gemini-data-analytics-query" ) type cloudGdaTransport struct { @@ -205,13 +205,13 @@ func getCloudGdaToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-gda-source": map[string]any{ - "kind": "cloud-gemini-data-analytics", + "type": "cloud-gemini-data-analytics", "projectId": "test-project", }, }, "tools": map[string]any{ "cloud-gda-query": map[string]any{ - "kind": cloudGdaToolKind, + "type": cloudGdaToolType, "source": "my-gda-source", "description": "Test GDA Tool", "location": "us-central1", diff --git a/tests/cloudhealthcare/cloud_healthcare_integration_test.go b/tests/cloudhealthcare/cloud_healthcare_integration_test.go index 4fdddcb84afa..72dac079285e 100644 --- a/tests/cloudhealthcare/cloud_healthcare_integration_test.go +++ b/tests/cloudhealthcare/cloud_healthcare_integration_test.go @@ -41,22 +41,22 @@ import ( ) var ( - healthcareSourceKind = "cloud-healthcare" - getDatasetToolKind = "cloud-healthcare-get-dataset" - listFHIRStoresToolKind = "cloud-healthcare-list-fhir-stores" - listDICOMStoresToolKind = "cloud-healthcare-list-dicom-stores" - getFHIRStoreToolKind = "cloud-healthcare-get-fhir-store" - getFHIRStoreMetricsToolKind = "cloud-healthcare-get-fhir-store-metrics" - getFHIRResourceToolKind = "cloud-healthcare-get-fhir-resource" - fhirPatientSearchToolKind = "cloud-healthcare-fhir-patient-search" - fhirPatientEverythingToolKind = "cloud-healthcare-fhir-patient-everything" - fhirFetchPageToolKind = "cloud-healthcare-fhir-fetch-page" - getDICOMStoreToolKind = "cloud-healthcare-get-dicom-store" - getDICOMStoreMetricsToolKind = "cloud-healthcare-get-dicom-store-metrics" - searchDICOMStudiesToolKind = "cloud-healthcare-search-dicom-studies" - searchDICOMSeriesToolKind = "cloud-healthcare-search-dicom-series" - searchDICOMInstancesToolKind = "cloud-healthcare-search-dicom-instances" - retrieveRenderedDICOMInstanceToolKind = "cloud-healthcare-retrieve-rendered-dicom-instance" + healthcareSourceType = "cloud-healthcare" + getDatasetToolType = "cloud-healthcare-get-dataset" + listFHIRStoresToolType = "cloud-healthcare-list-fhir-stores" + listDICOMStoresToolType = "cloud-healthcare-list-dicom-stores" + getFHIRStoreToolType = "cloud-healthcare-get-fhir-store" + getFHIRStoreMetricsToolType = "cloud-healthcare-get-fhir-store-metrics" + getFHIRResourceToolType = "cloud-healthcare-get-fhir-resource" + fhirPatientSearchToolType = "cloud-healthcare-fhir-patient-search" + fhirPatientEverythingToolType = "cloud-healthcare-fhir-patient-everything" + fhirFetchPageToolType = "cloud-healthcare-fhir-fetch-page" + getDICOMStoreToolType = "cloud-healthcare-get-dicom-store" + getDICOMStoreMetricsToolType = "cloud-healthcare-get-dicom-store-metrics" + searchDICOMStudiesToolType = "cloud-healthcare-search-dicom-studies" + searchDICOMSeriesToolType = "cloud-healthcare-search-dicom-series" + searchDICOMInstancesToolType = "cloud-healthcare-search-dicom-instances" + retrieveRenderedDICOMInstanceToolType = "cloud-healthcare-retrieve-rendered-dicom-instance" healthcareProject = os.Getenv("HEALTHCARE_PROJECT") healthcareRegion = os.Getenv("HEALTHCARE_REGION") healthcareDataset = os.Getenv("HEALTHCARE_DATASET") @@ -92,7 +92,7 @@ func getHealthcareVars(t *testing.T) map[string]any { t.Fatal("'HEALTHCARE_PREPOPULATED_DICOM_STORE' not set") } return map[string]any{ - "kind": healthcareSourceKind, + "type": healthcareSourceType, "project": healthcareProject, "region": healthcareRegion, "dataset": healthcareDataset, @@ -182,12 +182,12 @@ func TestHealthcareToolWithStoreRestriction(t *testing.T) { // Configure tool toolsConfig := map[string]any{ "list-fhir-stores-restricted": map[string]any{ - "kind": "cloud-healthcare-list-fhir-stores", + "type": "cloud-healthcare-list-fhir-stores", "source": "my-instance", "description": "Tool to list fhir stores", }, "list-dicom-stores-restricted": map[string]any{ - "kind": "cloud-healthcare-list-dicom-stores", + "type": "cloud-healthcare-list-dicom-stores", "source": "my-instance", "description": "Tool to list dicom stores", }, @@ -336,157 +336,157 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, "tools": map[string]any{ "my-get-dataset-tool": map[string]any{ - "kind": getDatasetToolKind, + "type": getDatasetToolType, "source": "my-instance", "description": "Tool to get a healthcare dataset", }, "my-list-fhir-stores-tool": map[string]any{ - "kind": listFHIRStoresToolKind, + "type": listFHIRStoresToolType, "source": "my-instance", "description": "Tool to list FHIR stores", }, "my-list-dicom-stores-tool": map[string]any{ - "kind": listDICOMStoresToolKind, + "type": listDICOMStoresToolType, "source": "my-instance", "description": "Tool to list DICOM stores", }, "my-get-fhir-store-tool": map[string]any{ - "kind": getFHIRStoreToolKind, + "type": getFHIRStoreToolType, "source": "my-instance", "description": "Tool to get a FHIR store", }, "my-get-fhir-store-metrics-tool": map[string]any{ - "kind": getFHIRStoreMetricsToolKind, + "type": getFHIRStoreMetricsToolType, "source": "my-instance", "description": "Tool to get FHIR store metrics", }, "my-get-fhir-resource-tool": map[string]any{ - "kind": getFHIRResourceToolKind, + "type": getFHIRResourceToolType, "source": "my-instance", "description": "Tool to get FHIR resource", }, "my-fhir-patient-search-tool": map[string]any{ - "kind": fhirPatientSearchToolKind, + "type": fhirPatientSearchToolType, "source": "my-instance", "description": "Tool to search for patients", }, "my-fhir-patient-everything-tool": map[string]any{ - "kind": fhirPatientEverythingToolKind, + "type": fhirPatientEverythingToolType, "source": "my-instance", "description": "Tool for patient everything", }, "my-fhir-fetch-page-tool": map[string]any{ - "kind": fhirFetchPageToolKind, + "type": fhirFetchPageToolType, "source": "my-instance", "description": "Tool to fetch a page of FHIR resources", }, "my-get-dicom-store-tool": map[string]any{ - "kind": getDICOMStoreToolKind, + "type": getDICOMStoreToolType, "source": "my-instance", "description": "Tool to get a DICOM store", }, "my-get-dicom-store-metrics-tool": map[string]any{ - "kind": getDICOMStoreMetricsToolKind, + "type": getDICOMStoreMetricsToolType, "source": "my-instance", "description": "Tool to get DICOM store metrics", }, "my-search-dicom-studies-tool": map[string]any{ - "kind": searchDICOMStudiesToolKind, + "type": searchDICOMStudiesToolType, "source": "my-instance", "description": "Tool to search DICOM studies", }, "my-search-dicom-series-tool": map[string]any{ - "kind": searchDICOMSeriesToolKind, + "type": searchDICOMSeriesToolType, "source": "my-instance", "description": "Tool to search DICOM series", }, "my-search-dicom-instances-tool": map[string]any{ - "kind": searchDICOMInstancesToolKind, + "type": searchDICOMInstancesToolType, "source": "my-instance", "description": "Tool to search DICOM instances", }, "my-retrieve-rendered-dicom-instance-tool": map[string]any{ - "kind": retrieveRenderedDICOMInstanceToolKind, + "type": retrieveRenderedDICOMInstanceToolType, "source": "my-instance", "description": "Tool to retrieve rendered DICOM instance", }, "my-client-auth-get-dataset-tool": map[string]any{ - "kind": getDatasetToolKind, + "type": getDatasetToolType, "source": "my-client-auth-source", "description": "Tool to get a healthcare dataset", }, "my-client-auth-list-fhir-stores-tool": map[string]any{ - "kind": listFHIRStoresToolKind, + "type": listFHIRStoresToolType, "source": "my-client-auth-source", "description": "Tool to list FHIR stores", }, "my-client-auth-list-dicom-stores-tool": map[string]any{ - "kind": listDICOMStoresToolKind, + "type": listDICOMStoresToolType, "source": "my-client-auth-source", "description": "Tool to list DICOM stores", }, "my-client-auth-get-fhir-store-tool": map[string]any{ - "kind": getFHIRStoreToolKind, + "type": getFHIRStoreToolType, "source": "my-client-auth-source", "description": "Tool to get a FHIR store", }, "my-client-auth-get-fhir-store-metrics-tool": map[string]any{ - "kind": getFHIRStoreMetricsToolKind, + "type": getFHIRStoreMetricsToolType, "source": "my-client-auth-source", "description": "Tool to get FHIR store metrics", }, "my-client-auth-get-fhir-resource-tool": map[string]any{ - "kind": getFHIRResourceToolKind, + "type": getFHIRResourceToolType, "source": "my-client-auth-source", "description": "Tool to get FHIR resource", }, "my-client-auth-fhir-patient-search-tool": map[string]any{ - "kind": fhirPatientSearchToolKind, + "type": fhirPatientSearchToolType, "source": "my-client-auth-source", "description": "Tool to search for patients", }, "my-client-auth-fhir-patient-everything-tool": map[string]any{ - "kind": fhirPatientEverythingToolKind, + "type": fhirPatientEverythingToolType, "source": "my-client-auth-source", "description": "Tool for patient everything", }, "my-client-auth-fhir-fetch-page-tool": map[string]any{ - "kind": fhirFetchPageToolKind, + "type": fhirFetchPageToolType, "source": "my-client-auth-source", "description": "Tool to fetch a page of FHIR resources", }, "my-client-auth-get-dicom-store-tool": map[string]any{ - "kind": getDICOMStoreToolKind, + "type": getDICOMStoreToolType, "source": "my-client-auth-source", "description": "Tool to get a DICOM store", }, "my-client-auth-get-dicom-store-metrics-tool": map[string]any{ - "kind": getDICOMStoreMetricsToolKind, + "type": getDICOMStoreMetricsToolType, "source": "my-client-auth-source", "description": "Tool to get DICOM store metrics", }, "my-client-auth-search-dicom-studies-tool": map[string]any{ - "kind": searchDICOMStudiesToolKind, + "type": searchDICOMStudiesToolType, "source": "my-client-auth-source", "description": "Tool to search DICOM studies", }, "my-client-auth-search-dicom-series-tool": map[string]any{ - "kind": searchDICOMSeriesToolKind, + "type": searchDICOMSeriesToolType, "source": "my-client-auth-source", "description": "Tool to search DICOM series", }, "my-client-auth-search-dicom-instances-tool": map[string]any{ - "kind": searchDICOMInstancesToolKind, + "type": searchDICOMInstancesToolType, "source": "my-client-auth-source", "description": "Tool to search DICOM instances", }, "my-client-auth-retrieve-rendered-dicom-instance-tool": map[string]any{ - "kind": retrieveRenderedDICOMInstanceToolKind, + "type": retrieveRenderedDICOMInstanceToolType, "source": "my-client-auth-source", "description": "Tool to retrieve rendered DICOM instance", }, "my-auth-get-dataset-tool": map[string]any{ - "kind": getDatasetToolKind, + "type": getDatasetToolType, "source": "my-instance", "description": "Tool to get a healthcare dataset with auth", "authRequired": []string{ @@ -494,7 +494,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-list-fhir-stores-tool": map[string]any{ - "kind": listFHIRStoresToolKind, + "type": listFHIRStoresToolType, "source": "my-instance", "description": "Tool to list FHIR stores with auth", "authRequired": []string{ @@ -502,7 +502,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-list-dicom-stores-tool": map[string]any{ - "kind": listDICOMStoresToolKind, + "type": listDICOMStoresToolType, "source": "my-instance", "description": "Tool to list DICOM stores with auth", "authRequired": []string{ @@ -510,7 +510,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-get-fhir-store-tool": map[string]any{ - "kind": getFHIRStoreToolKind, + "type": getFHIRStoreToolType, "source": "my-instance", "description": "Tool to get a FHIR store", "authRequired": []string{ @@ -518,7 +518,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-get-fhir-store-metrics-tool": map[string]any{ - "kind": getFHIRStoreMetricsToolKind, + "type": getFHIRStoreMetricsToolType, "source": "my-instance", "description": "Tool to get FHIR store metrics", "authRequired": []string{ @@ -526,7 +526,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-get-fhir-resource-tool": map[string]any{ - "kind": getFHIRResourceToolKind, + "type": getFHIRResourceToolType, "source": "my-instance", "description": "Tool to get FHIR resource", "authRequired": []string{ @@ -534,7 +534,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-fhir-patient-search-tool": map[string]any{ - "kind": fhirPatientSearchToolKind, + "type": fhirPatientSearchToolType, "source": "my-instance", "description": "Tool to search for patients", "authRequired": []string{ @@ -542,7 +542,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-fhir-patient-everything-tool": map[string]any{ - "kind": fhirPatientEverythingToolKind, + "type": fhirPatientEverythingToolType, "source": "my-instance", "description": "Tool for patient everything", "authRequired": []string{ @@ -550,7 +550,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-fhir-fetch-page-tool": map[string]any{ - "kind": fhirFetchPageToolKind, + "type": fhirFetchPageToolType, "source": "my-instance", "description": "Tool to fetch a page of FHIR resources", "authRequired": []string{ @@ -558,7 +558,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-get-dicom-store-tool": map[string]any{ - "kind": getDICOMStoreToolKind, + "type": getDICOMStoreToolType, "source": "my-instance", "description": "Tool to get a DICOM store", "authRequired": []string{ @@ -566,7 +566,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-get-dicom-store-metrics-tool": map[string]any{ - "kind": getDICOMStoreMetricsToolKind, + "type": getDICOMStoreMetricsToolType, "source": "my-instance", "description": "Tool to get DICOM store metrics", "authRequired": []string{ @@ -574,7 +574,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-search-dicom-studies-tool": map[string]any{ - "kind": searchDICOMStudiesToolKind, + "type": searchDICOMStudiesToolType, "source": "my-instance", "description": "Tool to search DICOM studies", "authRequired": []string{ @@ -582,7 +582,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-search-dicom-series-tool": map[string]any{ - "kind": searchDICOMSeriesToolKind, + "type": searchDICOMSeriesToolType, "source": "my-instance", "description": "Tool to search DICOM series", "authRequired": []string{ @@ -590,7 +590,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-search-dicom-instances-tool": map[string]any{ - "kind": searchDICOMInstancesToolKind, + "type": searchDICOMInstancesToolType, "source": "my-instance", "description": "Tool to search DICOM instances", "authRequired": []string{ @@ -598,7 +598,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "my-auth-retrieve-rendered-dicom-instance-tool": map[string]any{ - "kind": retrieveRenderedDICOMInstanceToolKind, + "type": retrieveRenderedDICOMInstanceToolType, "source": "my-instance", "description": "Tool to retrieve rendered DICOM instance", "authRequired": []string{ @@ -608,7 +608,7 @@ func getToolsConfig(sourceConfig map[string]any) map[string]any { }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, @@ -622,7 +622,7 @@ func addClientAuthSourceConfig(t *testing.T, config map[string]any) map[string]a t.Fatalf("unable to get sources from config") } sources["my-client-auth-source"] = map[string]any{ - "kind": healthcareSourceKind, + "type": healthcareSourceType, "project": healthcareProject, "region": healthcareRegion, "dataset": healthcareDataset, diff --git a/tests/cloudmonitoring/cloud_monitoring_integration_test.go b/tests/cloudmonitoring/cloud_monitoring_integration_test.go index f5833244a6e6..54295cf5fb3f 100644 --- a/tests/cloudmonitoring/cloud_monitoring_integration_test.go +++ b/tests/cloudmonitoring/cloud_monitoring_integration_test.go @@ -49,7 +49,7 @@ func TestTool_Invoke(t *testing.T) { tool := cloudmonitoring.Tool{ Config: cloudmonitoring.Config{ Name: "test-cloudmonitoring", - Kind: "cloud-monitoring-query-prometheus", + Type: "cloud-monitoring-query-prometheus", Description: "Test Cloudmonitoring Tool", }, AllParams: parameters.Parameters{}, @@ -93,7 +93,7 @@ func TestTool_Invoke_Error(t *testing.T) { tool := cloudmonitoring.Tool{ Config: cloudmonitoring.Config{ Name: "test-cloudmonitoring", - Kind: "clou-monitoring-query-prometheus", + Type: "clou-monitoring-query-prometheus", Description: "Test Cloudmonitoring Tool", }, AllParams: parameters.Parameters{}, diff --git a/tests/cloudsql/cloud_sql_clone_instance_test.go b/tests/cloudsql/cloud_sql_clone_instance_test.go index f41062cb9ac9..024c24d153bb 100644 --- a/tests/cloudsql/cloud_sql_clone_instance_test.go +++ b/tests/cloudsql/cloud_sql_clone_instance_test.go @@ -38,7 +38,7 @@ import ( ) var ( - cloneInstanceToolKind = "cloud-sql-clone-instance" + cloneInstanceToolType = "cloud-sql-clone-instance" ) type cloneInstanceTransport struct { @@ -231,12 +231,12 @@ func getCloneInstanceToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "clone-instance": map[string]any{ - "kind": cloneInstanceToolKind, + "type": cloneInstanceToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsql/cloud_sql_create_backup_test.go b/tests/cloudsql/cloud_sql_create_backup_test.go index d9b7d052649c..daebe9a7321a 100644 --- a/tests/cloudsql/cloud_sql_create_backup_test.go +++ b/tests/cloudsql/cloud_sql_create_backup_test.go @@ -36,7 +36,7 @@ import ( ) var ( - createBackupToolKind = "cloud-sql-create-backup" + createBackupToolType = "cloud-sql-create-backup" ) type createBackupTransport struct { @@ -219,12 +219,12 @@ func getCreateBackupToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-backup": map[string]any{ - "kind": createBackupToolKind, + "type": createBackupToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsql/cloud_sql_create_database_test.go b/tests/cloudsql/cloud_sql_create_database_test.go index a87bc8200b73..c68d7dfb121e 100644 --- a/tests/cloudsql/cloud_sql_create_database_test.go +++ b/tests/cloudsql/cloud_sql_create_database_test.go @@ -35,7 +35,7 @@ import ( ) var ( - createDatabaseToolKind = "cloud-sql-create-database" + createDatabaseToolType = "cloud-sql-create-database" ) type createDatabaseTransport struct { @@ -217,12 +217,12 @@ func getCreateDatabaseToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-database": map[string]any{ - "kind": createDatabaseToolKind, + "type": createDatabaseToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsql/cloud_sql_create_users_test.go b/tests/cloudsql/cloud_sql_create_users_test.go index 39cc4320f1a3..77978c4506c3 100644 --- a/tests/cloudsql/cloud_sql_create_users_test.go +++ b/tests/cloudsql/cloud_sql_create_users_test.go @@ -35,7 +35,7 @@ import ( ) var ( - createUserToolKind = "cloud-sql-create-users" + createUserToolType = "cloud-sql-create-users" ) type createUsersTransport struct { @@ -229,12 +229,12 @@ func getCreateUsersToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-user": map[string]any{ - "kind": createUserToolKind, + "type": createUserToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsql/cloud_sql_get_instances_test.go b/tests/cloudsql/cloud_sql_get_instances_test.go index dc920a80dd3d..709a50145070 100644 --- a/tests/cloudsql/cloud_sql_get_instances_test.go +++ b/tests/cloudsql/cloud_sql_get_instances_test.go @@ -35,7 +35,7 @@ import ( ) var ( - getInstancesToolKind = "cloud-sql-get-instance" + getInstancesToolType = "cloud-sql-get-instance" ) type getInstancesTransport struct { @@ -231,21 +231,21 @@ func getToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, "my-invalid-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", "useClientOAuth": true, }, }, "tools": map[string]any{ "get-instance-1": map[string]any{ - "kind": getInstancesToolKind, + "type": getInstancesToolType, "description": "get instance 1", "source": "my-cloud-sql-source", }, "get-instance-2": map[string]any{ - "kind": getInstancesToolKind, + "type": getInstancesToolType, "description": "get instance 2", "source": "my-invalid-cloud-sql-source", }, diff --git a/tests/cloudsql/cloud_sql_list_databases_test.go b/tests/cloudsql/cloud_sql_list_databases_test.go index 6ee0f9b9eb9c..34719d2b0396 100644 --- a/tests/cloudsql/cloud_sql_list_databases_test.go +++ b/tests/cloudsql/cloud_sql_list_databases_test.go @@ -34,7 +34,7 @@ import ( ) var ( - listDatabasesToolKind = "cloud-sql-list-databases" + listDatabasesToolType = "cloud-sql-list-databases" ) type listDatabasesTransport struct { @@ -200,12 +200,12 @@ func getListDatabasesToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "list-databases": map[string]any{ - "kind": listDatabasesToolKind, + "type": listDatabasesToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsql/cloudsql_list_instances_test.go b/tests/cloudsql/cloudsql_list_instances_test.go index 093765dfeb6a..7978fa5f65c0 100644 --- a/tests/cloudsql/cloudsql_list_instances_test.go +++ b/tests/cloudsql/cloudsql_list_instances_test.go @@ -171,20 +171,20 @@ func getListInstanceToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, "my-invalid-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", "useClientOAuth": true, }, }, "tools": map[string]any{ "list-instances": map[string]any{ - "kind": "cloud-sql-list-instances", + "type": "cloud-sql-list-instances", "source": "my-cloud-sql-source", }, "list-instances-fail": map[string]any{ - "kind": "cloud-sql-list-instances", + "type": "cloud-sql-list-instances", "description": "list instances", "source": "my-invalid-cloud-sql-source", }, diff --git a/tests/cloudsql/cloudsql_wait_for_operation_test.go b/tests/cloudsql/cloudsql_wait_for_operation_test.go index ab8cab808ec8..33c48077f21e 100644 --- a/tests/cloudsql/cloudsql_wait_for_operation_test.go +++ b/tests/cloudsql/cloudsql_wait_for_operation_test.go @@ -37,7 +37,7 @@ import ( ) var ( - cloudsqlWaitToolKind = "cloud-sql-wait-for-operation" + cloudsqlWaitToolType = "cloud-sql-wait-for-operation" ) type waitForOperationTransport struct { @@ -291,22 +291,22 @@ func getCloudSQLWaitToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "wait-for-op1": map[string]any{ - "kind": cloudsqlWaitToolKind, + "type": cloudsqlWaitToolType, "source": "my-cloud-sql-source", "description": "wait for op1", }, "wait-for-op2": map[string]any{ - "kind": cloudsqlWaitToolKind, + "type": cloudsqlWaitToolType, "source": "my-cloud-sql-source", "description": "wait for op2", }, "wait-for-op3": map[string]any{ - "kind": cloudsqlWaitToolKind, + "type": cloudsqlWaitToolType, "source": "my-cloud-sql-source", "description": "wait for op3", }, diff --git a/tests/cloudsqlmssql/cloud_sql_mssql_create_instance_integration_test.go b/tests/cloudsqlmssql/cloud_sql_mssql_create_instance_integration_test.go index 05bbe2d8e551..f46886965652 100644 --- a/tests/cloudsqlmssql/cloud_sql_mssql_create_instance_integration_test.go +++ b/tests/cloudsqlmssql/cloud_sql_mssql_create_instance_integration_test.go @@ -36,7 +36,7 @@ import ( ) var ( - createInstanceToolKind = "cloud-sql-mssql-create-instance" + createInstanceToolType = "cloud-sql-mssql-create-instance" ) type createInstanceTransport struct { @@ -260,16 +260,16 @@ func getCreateInstanceToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-instance-prod": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, "create-instance-dev": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsqlmssql/cloud_sql_mssql_integration_test.go b/tests/cloudsqlmssql/cloud_sql_mssql_integration_test.go index b53ca030cedb..aac0819715c8 100644 --- a/tests/cloudsqlmssql/cloud_sql_mssql_integration_test.go +++ b/tests/cloudsqlmssql/cloud_sql_mssql_integration_test.go @@ -34,8 +34,8 @@ import ( ) var ( - CloudSQLMSSQLSourceKind = "cloud-sql-mssql" - CloudSQLMSSQLToolKind = "mssql-sql" + CloudSQLMSSQLSourceType = "cloud-sql-mssql" + CloudSQLMSSQLToolType = "mssql-sql" CloudSQLMSSQLProject = os.Getenv("CLOUD_SQL_MSSQL_PROJECT") CloudSQLMSSQLRegion = os.Getenv("CLOUD_SQL_MSSQL_REGION") CloudSQLMSSQLInstance = os.Getenv("CLOUD_SQL_MSSQL_INSTANCE") @@ -61,7 +61,7 @@ func getCloudSQLMSSQLVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": CloudSQLMSSQLSourceKind, + "type": CloudSQLMSSQLSourceType, "project": CloudSQLMSSQLProject, "instance": CloudSQLMSSQLInstance, "region": CloudSQLMSSQLRegion, @@ -137,10 +137,10 @@ func TestCloudSQLMSSQLToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLMSSQLToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLMSSQLToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddMSSQLExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMSSQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLMSSQLToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLMSSQLToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddMSSQLPrebuiltToolConfig(t, toolsFile) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) @@ -191,7 +191,7 @@ func TestCloudSQLMSSQLIpConnection(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { sourceConfig["ipType"] = tc.ipType - err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLMSSQLToolKind) + err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLMSSQLToolType) if err != nil { t.Fatalf("Connection test failure: %s", err) } diff --git a/tests/cloudsqlmysql/cloud_sql_mysql_create_instance_integration_test.go b/tests/cloudsqlmysql/cloud_sql_mysql_create_instance_integration_test.go index 7ddec92faa4e..4af92f764820 100644 --- a/tests/cloudsqlmysql/cloud_sql_mysql_create_instance_integration_test.go +++ b/tests/cloudsqlmysql/cloud_sql_mysql_create_instance_integration_test.go @@ -36,7 +36,7 @@ import ( ) var ( - createInstanceToolKind = "cloud-sql-mysql-create-instance" + createInstanceToolType = "cloud-sql-mysql-create-instance" ) type createInstanceTransport struct { @@ -261,16 +261,16 @@ func getCreateInstanceToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-instance-prod": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, "create-instance-dev": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsqlmysql/cloud_sql_mysql_integration_test.go b/tests/cloudsqlmysql/cloud_sql_mysql_integration_test.go index 55b30358688d..b60e78fc727a 100644 --- a/tests/cloudsqlmysql/cloud_sql_mysql_integration_test.go +++ b/tests/cloudsqlmysql/cloud_sql_mysql_integration_test.go @@ -33,8 +33,8 @@ import ( ) var ( - CloudSQLMySQLSourceKind = "cloud-sql-mysql" - CloudSQLMySQLToolKind = "mysql-sql" + CloudSQLMySQLSourceType = "cloud-sql-mysql" + CloudSQLMySQLToolType = "mysql-sql" CloudSQLMySQLProject = os.Getenv("CLOUD_SQL_MYSQL_PROJECT") CloudSQLMySQLRegion = os.Getenv("CLOUD_SQL_MYSQL_REGION") CloudSQLMySQLInstance = os.Getenv("CLOUD_SQL_MYSQL_INSTANCE") @@ -60,7 +60,7 @@ func getCloudSQLMySQLVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": CloudSQLMySQLSourceKind, + "type": CloudSQLMySQLSourceType, "project": CloudSQLMySQLProject, "instance": CloudSQLMySQLInstance, "region": CloudSQLMySQLRegion, @@ -129,10 +129,10 @@ func TestCloudSQLMySQLToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLMySQLToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLMySQLToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddMySqlExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMySQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLMySQLToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLMySQLToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddMySQLPrebuiltToolConfig(t, toolsFile) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) @@ -186,7 +186,7 @@ func TestCloudSQLMySQLIpConnection(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { sourceConfig["ipType"] = tc.ipType - err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLMySQLToolKind) + err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLMySQLToolType) if err != nil { t.Fatalf("Connection test failure: %s", err) } @@ -200,7 +200,7 @@ func TestCloudSQLMySQLIAMConnection(t *testing.T) { serviceAccountEmail, _, _ := strings.Cut(tests.ServiceAccountEmail, "@") noPassSourceConfig := map[string]any{ - "kind": CloudSQLMySQLSourceKind, + "type": CloudSQLMySQLSourceType, "project": CloudSQLMySQLProject, "instance": CloudSQLMySQLInstance, "region": CloudSQLMySQLRegion, @@ -208,7 +208,7 @@ func TestCloudSQLMySQLIAMConnection(t *testing.T) { "user": serviceAccountEmail, } noUserSourceConfig := map[string]any{ - "kind": CloudSQLMySQLSourceKind, + "type": CloudSQLMySQLSourceType, "project": CloudSQLMySQLProject, "instance": CloudSQLMySQLInstance, "region": CloudSQLMySQLRegion, @@ -216,7 +216,7 @@ func TestCloudSQLMySQLIAMConnection(t *testing.T) { "password": "random", } noUserNoPassSourceConfig := map[string]any{ - "kind": CloudSQLMySQLSourceKind, + "type": CloudSQLMySQLSourceType, "project": CloudSQLMySQLProject, "instance": CloudSQLMySQLInstance, "region": CloudSQLMySQLRegion, @@ -260,7 +260,7 @@ func TestCloudSQLMySQLIAMConnection(t *testing.T) { }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": CloudSQLMySQLToolKind, + "type": CloudSQLMySQLToolType, "source": uniqueSourceName, "description": "Simple tool to test end to end functionality.", "statement": "SELECT 1;", diff --git a/tests/cloudsqlpg/cloud_sql_pg_create_instances_test.go b/tests/cloudsqlpg/cloud_sql_pg_create_instances_test.go index 85fb01108544..aaef8f5bcc8a 100644 --- a/tests/cloudsqlpg/cloud_sql_pg_create_instances_test.go +++ b/tests/cloudsqlpg/cloud_sql_pg_create_instances_test.go @@ -36,7 +36,7 @@ import ( ) var ( - createInstanceToolKind = "cloud-sql-postgres-create-instance" + createInstanceToolType = "cloud-sql-postgres-create-instance" ) type createInstanceTransport struct { @@ -262,16 +262,16 @@ func getCreateInstanceToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "create-instance-prod": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, "create-instance-dev": map[string]any{ - "kind": createInstanceToolKind, + "type": createInstanceToolType, "source": "my-cloud-sql-source", }, }, diff --git a/tests/cloudsqlpg/cloud_sql_pg_integration_test.go b/tests/cloudsqlpg/cloud_sql_pg_integration_test.go index dc8ecb27bf91..e6340cb87172 100644 --- a/tests/cloudsqlpg/cloud_sql_pg_integration_test.go +++ b/tests/cloudsqlpg/cloud_sql_pg_integration_test.go @@ -32,8 +32,8 @@ import ( ) var ( - CloudSQLPostgresSourceKind = "cloud-sql-postgres" - CloudSQLPostgresToolKind = "postgres-sql" + CloudSQLPostgresSourceType = "cloud-sql-postgres" + CloudSQLPostgresToolType = "postgres-sql" CloudSQLPostgresProject = os.Getenv("CLOUD_SQL_POSTGRES_PROJECT") CloudSQLPostgresRegion = os.Getenv("CLOUD_SQL_POSTGRES_REGION") CloudSQLPostgresInstance = os.Getenv("CLOUD_SQL_POSTGRES_INSTANCE") @@ -59,7 +59,7 @@ func getCloudSQLPgVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": CloudSQLPostgresSourceKind, + "type": CloudSQLPostgresSourceType, "project": CloudSQLPostgresProject, "instance": CloudSQLPostgresInstance, "region": CloudSQLPostgresRegion, @@ -137,14 +137,14 @@ func TestCloudSQLPgSimpleToolEndpoints(t *testing.T) { defer tearDownVectorTable(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLPostgresToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, CloudSQLPostgresToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddExecuteSqlConfig(t, toolsFile, "postgres-execute-sql") tmplSelectCombined, tmplSelectFilterCombined := tests.GetPostgresSQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLPostgresToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, CloudSQLPostgresToolType, tmplSelectCombined, tmplSelectFilterCombined, "") // Add semantic search tool config insertStmt, searchStmt := tests.GetPostgresVectorSearchStmts(vectorTableName) - toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, CloudSQLPostgresToolKind, insertStmt, searchStmt) + toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, CloudSQLPostgresToolType, insertStmt, searchStmt) toolsFile = tests.AddPostgresPrebuiltConfig(t, toolsFile) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) @@ -217,7 +217,7 @@ func TestCloudSQLPgIpConnection(t *testing.T) { for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { sourceConfig["ipType"] = tc.ipType - err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLPostgresToolKind) + err := tests.RunSourceConnectionTest(t, sourceConfig, CloudSQLPostgresToolType) if err != nil { t.Fatalf("Connection test failure: %s", err) } @@ -231,7 +231,7 @@ func TestCloudSQLPgIAMConnection(t *testing.T) { serviceAccountEmail := strings.TrimSuffix(tests.ServiceAccountEmail, ".gserviceaccount.com") noPassSourceConfig := map[string]any{ - "kind": CloudSQLPostgresSourceKind, + "type": CloudSQLPostgresSourceType, "project": CloudSQLPostgresProject, "instance": CloudSQLPostgresInstance, "region": CloudSQLPostgresRegion, @@ -240,7 +240,7 @@ func TestCloudSQLPgIAMConnection(t *testing.T) { } noUserSourceConfig := map[string]any{ - "kind": CloudSQLPostgresSourceKind, + "type": CloudSQLPostgresSourceType, "project": CloudSQLPostgresProject, "instance": CloudSQLPostgresInstance, "region": CloudSQLPostgresRegion, @@ -249,7 +249,7 @@ func TestCloudSQLPgIAMConnection(t *testing.T) { } noUserNoPassSourceConfig := map[string]any{ - "kind": CloudSQLPostgresSourceKind, + "type": CloudSQLPostgresSourceType, "project": CloudSQLPostgresProject, "instance": CloudSQLPostgresInstance, "region": CloudSQLPostgresRegion, @@ -278,7 +278,7 @@ func TestCloudSQLPgIAMConnection(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - err := tests.RunSourceConnectionTest(t, tc.sourceConfig, CloudSQLPostgresToolKind) + err := tests.RunSourceConnectionTest(t, tc.sourceConfig, CloudSQLPostgresToolType) if err != nil { if tc.isErr { return diff --git a/tests/cloudsqlpg/cloud_sql_pg_upgrade_precheck_test.go b/tests/cloudsqlpg/cloud_sql_pg_upgrade_precheck_test.go index 7db191f5beec..881e4bee152a 100644 --- a/tests/cloudsqlpg/cloud_sql_pg_upgrade_precheck_test.go +++ b/tests/cloudsqlpg/cloud_sql_pg_upgrade_precheck_test.go @@ -35,7 +35,7 @@ import ( ) var ( - preCheckToolKind = "postgres-upgrade-precheck" + preCheckToolType = "postgres-upgrade-precheck" ) type preCheckTransport struct { @@ -264,13 +264,13 @@ func TestPreCheckToolEndpoints(t *testing.T) { name: "successful precheck - with warnings", toolName: "precheck-tool", body: `{"project": "p1", "instance": "instance-warnings", "targetDatabaseVersion": "POSTGRES_18"}`, - want: `{"preCheckResponse":[{"actionsRequired":["Check documentation."],"kind":"","message":"This is a warning.","messageType":"WARNING"}]}`, + want: `{"preCheckResponse":[{"actionsRequired":["Check documentation."],"type":"","message":"This is a warning.","messageType":"WARNING"}]}`, }, { name: "successful precheck - with errors", toolName: "precheck-tool", body: `{"project": "p1", "instance": "instance-errors", "targetDatabaseVersion": "POSTGRES_18"}`, - want: `{"preCheckResponse":[{"actionsRequired":["Fix this now."],"kind":"","message":"This is a critical error.","messageType":"ERROR"}]}`, + want: `{"preCheckResponse":[{"actionsRequired":["Fix this now."],"type":"","message":"This is a critical error.","messageType":"ERROR"}]}`, }, { name: "instance not found", @@ -368,12 +368,12 @@ func getPreCheckToolsConfig() map[string]any { return map[string]any{ "sources": map[string]any{ "my-cloud-sql-source": map[string]any{ - "kind": "cloud-sql-admin", + "type": "cloud-sql-admin", }, }, "tools": map[string]any{ "precheck-tool": map[string]any{ - "kind": preCheckToolKind, + "type": preCheckToolType, "source": "my-cloud-sql-source", "authRequired": []string{ "https://www.googleapis.com/auth/cloud-platform", diff --git a/tests/common.go b/tests/common.go index a567b5eae8ee..fb56159e51d3 100644 --- a/tests/common.go +++ b/tests/common.go @@ -24,7 +24,6 @@ import ( "strings" "testing" - "github.com/goccy/go-yaml" "github.com/google/go-cmp/cmp" "github.com/googleapis/genai-toolbox/internal/server" "github.com/googleapis/genai-toolbox/internal/sources/cloudsqlmysql" @@ -34,7 +33,7 @@ import ( ) // GetToolsConfig returns a mock tools config file -func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { +func GetToolsConfig(sourceConfig map[string]any, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { // Write config into a file and pass it to command toolsFile := map[string]any{ "sources": map[string]any{ @@ -42,19 +41,19 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "statement": "SELECT 1", }, "my-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": paramToolStatement, @@ -72,7 +71,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-tool-by-id": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": idParamToolStmt, @@ -85,7 +84,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-tool-by-name": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": nameParamToolStmt, @@ -99,7 +98,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-array-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with array params.", "statement": arrayToolStatement, @@ -127,7 +126,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-auth-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", // statement to auto-fill authenticated parameter @@ -147,7 +146,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-auth-required-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "statement": "SELECT 1", @@ -156,7 +155,7 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i }, }, "my-fail-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test statement with incorrect syntax.", "statement": "SELEC 1;", @@ -168,18 +167,18 @@ func GetToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, i } // AddExecuteSqlConfig gets the tools config for `execute-sql` tools -func AddExecuteSqlConfig(t *testing.T, config map[string]any, toolKind string) map[string]any { +func AddExecuteSqlConfig(t *testing.T, config map[string]any, toolType string) map[string]any { tools, ok := config["tools"].(map[string]any) if !ok { t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -192,28 +191,28 @@ func AddExecuteSqlConfig(t *testing.T, config map[string]any, toolKind string) m func AddPostgresPrebuiltConfig(t *testing.T, config map[string]any) map[string]any { var ( - PostgresListSchemasToolKind = "postgres-list-schemas" - PostgresListTablesToolKind = "postgres-list-tables" - PostgresListActiveQueriesToolKind = "postgres-list-active-queries" - PostgresListInstalledExtensionsToolKind = "postgres-list-installed-extensions" - PostgresListAvailableExtensionsToolKind = "postgres-list-available-extensions" - PostgresListViewsToolKind = "postgres-list-views" - PostgresDatabaseOverviewToolKind = "postgres-database-overview" - PostgresListTriggersToolKind = "postgres-list-triggers" - PostgresListIndexesToolKind = "postgres-list-indexes" - PostgresListSequencesToolKind = "postgres-list-sequences" - PostgresLongRunningTransactionsToolKind = "postgres-long-running-transactions" - PostgresListLocksToolKind = "postgres-list-locks" - PostgresReplicationStatsToolKind = "postgres-replication-stats" - PostgresListQueryStatsToolKind = "postgres-list-query-stats" - PostgresGetColumnCardinalityToolKind = "postgres-get-column-cardinality" + PostgresListSchemasToolType = "postgres-list-schemas" + PostgresListTablesToolType = "postgres-list-tables" + PostgresListActiveQueriesToolType = "postgres-list-active-queries" + PostgresListInstalledExtensionsToolType = "postgres-list-installed-extensions" + PostgresListAvailableExtensionsToolType = "postgres-list-available-extensions" + PostgresListViewsToolType = "postgres-list-views" + PostgresDatabaseOverviewToolType = "postgres-database-overview" + PostgresListTriggersToolType = "postgres-list-triggers" + PostgresListIndexesToolType = "postgres-list-indexes" + PostgresListSequencesToolType = "postgres-list-sequences" + PostgresLongRunningTransactionsToolType = "postgres-long-running-transactions" + PostgresListLocksToolType = "postgres-list-locks" + PostgresReplicationStatsToolType = "postgres-replication-stats" + PostgresListQueryStatsToolType = "postgres-list-query-stats" + PostgresGetColumnCardinalityToolType = "postgres-get-column-cardinality" PostgresListTableStats = "postgres-list-table-stats" - PostgresListPublicationTablesToolKind = "postgres-list-publication-tables" - PostgresListTablespacesToolKind = "postgres-list-tablespaces" - PostgresListPGSettingsToolKind = "postgres-list-pg-settings" - PostgresListDatabaseStatsToolKind = "postgres-list-database-stats" - PostgresListRolesToolKind = "postgres-list-roles" - PostgresListStoredProcedureToolKind = "postgres-list-stored-procedure" + PostgresListPublicationTablesToolType = "postgres-list-publication-tables" + PostgresListTablespacesToolType = "postgres-list-tablespaces" + PostgresListPGSettingsToolType = "postgres-list-pg-settings" + PostgresListDatabaseStatsToolType = "postgres-list-database-stats" + PostgresListRolesToolType = "postgres-list-roles" + PostgresListStoredProcedureToolType = "postgres-list-stored-procedure" ) tools, ok := config["tools"].(map[string]any) @@ -221,106 +220,106 @@ func AddPostgresPrebuiltConfig(t *testing.T, config map[string]any) map[string]a t.Fatalf("unable to get tools from config") } tools["list_tables"] = map[string]any{ - "kind": PostgresListTablesToolKind, + "type": PostgresListTablesToolType, "source": "my-instance", "description": "Lists tables in the database.", } tools["list_active_queries"] = map[string]any{ - "kind": PostgresListActiveQueriesToolKind, + "type": PostgresListActiveQueriesToolType, "source": "my-instance", "description": "Lists active queries in the database.", } tools["list_installed_extensions"] = map[string]any{ - "kind": PostgresListInstalledExtensionsToolKind, + "type": PostgresListInstalledExtensionsToolType, "source": "my-instance", "description": "Lists installed extensions in the database.", } tools["list_available_extensions"] = map[string]any{ - "kind": PostgresListAvailableExtensionsToolKind, + "type": PostgresListAvailableExtensionsToolType, "source": "my-instance", "description": "Lists available extensions in the database.", } tools["list_views"] = map[string]any{ - "kind": PostgresListViewsToolKind, + "type": PostgresListViewsToolType, "source": "my-instance", } tools["list_schemas"] = map[string]any{ - "kind": PostgresListSchemasToolKind, + "type": PostgresListSchemasToolType, "source": "my-instance", } tools["database_overview"] = map[string]any{ - "kind": PostgresDatabaseOverviewToolKind, + "type": PostgresDatabaseOverviewToolType, "source": "my-instance", } tools["list_triggers"] = map[string]any{ - "kind": PostgresListTriggersToolKind, + "type": PostgresListTriggersToolType, "source": "my-instance", } tools["list_indexes"] = map[string]any{ - "kind": PostgresListIndexesToolKind, + "type": PostgresListIndexesToolType, "source": "my-instance", } tools["list_sequences"] = map[string]any{ - "kind": PostgresListSequencesToolKind, + "type": PostgresListSequencesToolType, "source": "my-instance", } tools["list_publication_tables"] = map[string]any{ - "kind": PostgresListPublicationTablesToolKind, + "type": PostgresListPublicationTablesToolType, "source": "my-instance", } tools["long_running_transactions"] = map[string]any{ - "kind": PostgresLongRunningTransactionsToolKind, + "type": PostgresLongRunningTransactionsToolType, "source": "my-instance", } tools["list_locks"] = map[string]any{ - "kind": PostgresListLocksToolKind, + "type": PostgresListLocksToolType, "source": "my-instance", } tools["replication_stats"] = map[string]any{ - "kind": PostgresReplicationStatsToolKind, + "type": PostgresReplicationStatsToolType, "source": "my-instance", } tools["list_query_stats"] = map[string]any{ - "kind": PostgresListQueryStatsToolKind, + "type": PostgresListQueryStatsToolType, "source": "my-instance", } tools["get_column_cardinality"] = map[string]any{ - "kind": PostgresGetColumnCardinalityToolKind, + "type": PostgresGetColumnCardinalityToolType, "source": "my-instance", } tools["list_table_stats"] = map[string]any{ - "kind": PostgresListTableStats, + "type": PostgresListTableStats, "source": "my-instance", } tools["list_tablespaces"] = map[string]any{ - "kind": PostgresListTablespacesToolKind, + "type": PostgresListTablespacesToolType, "source": "my-instance", } tools["list_pg_settings"] = map[string]any{ - "kind": PostgresListPGSettingsToolKind, + "type": PostgresListPGSettingsToolType, "source": "my-instance", } tools["list_database_stats"] = map[string]any{ - "kind": PostgresListDatabaseStatsToolKind, + "type": PostgresListDatabaseStatsToolType, "source": "my-instance", } tools["list_roles"] = map[string]any{ - "kind": PostgresListRolesToolKind, + "type": PostgresListRolesToolType, "source": "my-instance", } tools["list_stored_procedure"] = map[string]any{ - "kind": PostgresListStoredProcedureToolKind, + "type": PostgresListStoredProcedureToolType, "source": "my-instance", } config["tools"] = tools return config } -func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplSelectCombined, tmplSelectFilterCombined string, tmplSelectAll string) map[string]any { +func AddTemplateParamConfig(t *testing.T, config map[string]any, toolType, tmplSelectCombined, tmplSelectFilterCombined string, tmplSelectAll string) map[string]any { toolsMap, ok := config["tools"].(map[string]any) if !ok { t.Fatalf("unable to get tools from config") @@ -332,7 +331,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS } toolsMap["create-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": "CREATE TABLE {{.tableName}} ({{array .columns}})", @@ -342,7 +341,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["insert-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Insert tool with template parameters", "statement": "INSERT INTO {{.tableName}} ({{array .columns}}) VALUES ({{.values}})", @@ -353,7 +352,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["select-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": selectAll, @@ -362,7 +361,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["select-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": tmplSelectCombined, @@ -372,7 +371,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["select-fields-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT {{array .fields}} FROM {{.tableName}} ORDER BY id", @@ -382,7 +381,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["select-filter-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": tmplSelectFilterCombined, @@ -393,7 +392,7 @@ func AddTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplS }, } toolsMap["drop-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Drop table tool with template parameters", "statement": "DROP TABLE IF EXISTS {{.tableName}}", @@ -412,12 +411,12 @@ func AddMySqlExecuteSqlConfig(t *testing.T, config map[string]any) map[string]an t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "mysql-execute-sql", + "type": "mysql-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "mysql-execute-sql", + "type": "mysql-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -435,27 +434,27 @@ func AddMySQLPrebuiltToolConfig(t *testing.T, config map[string]any) map[string] t.Fatalf("unable to get tools from config") } tools["list_tables"] = map[string]any{ - "kind": "mysql-list-tables", + "type": "mysql-list-tables", "source": "my-instance", "description": "Lists tables in the database.", } tools["list_active_queries"] = map[string]any{ - "kind": "mysql-list-active-queries", + "type": "mysql-list-active-queries", "source": "my-instance", "description": "Lists active queries in the database.", } tools["list_tables_missing_unique_indexes"] = map[string]any{ - "kind": "mysql-list-tables-missing-unique-indexes", + "type": "mysql-list-tables-missing-unique-indexes", "source": "my-instance", "description": "Lists tables that do not have primary or unique indexes in the database.", } tools["list_table_fragmentation"] = map[string]any{ - "kind": "mysql-list-table-fragmentation", + "type": "mysql-list-table-fragmentation", "source": "my-instance", "description": "Lists table fragmentation in the database.", } tools["get_query_plan"] = map[string]any{ - "kind": "mysql-get-query-plan", + "type": "mysql-get-query-plan", "source": "my-instance", "description": "Gets the query plan for a SQL statement.", } @@ -470,12 +469,12 @@ func AddMSSQLExecuteSqlConfig(t *testing.T, config map[string]any) map[string]an t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "mssql-execute-sql", + "type": "mssql-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "mssql-execute-sql", + "type": "mssql-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -493,7 +492,7 @@ func AddMSSQLPrebuiltToolConfig(t *testing.T, config map[string]any) map[string] t.Fatalf("unable to get tools from config") } tools["list_tables"] = map[string]any{ - "kind": "mssql-list-tables", + "type": "mssql-list-tables", "source": "my-instance", "description": "Lists tables in the database.", } @@ -501,7 +500,7 @@ func AddMSSQLPrebuiltToolConfig(t *testing.T, config map[string]any) map[string] return config } -// GetPostgresSQLParamToolInfo returns statements and param for my-tool postgres-sql kind +// GetPostgresSQLParamToolInfo returns statements and param for my-tool postgres-sql type func GetPostgresSQLParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id SERIAL PRIMARY KEY, name TEXT);", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name) VALUES ($1), ($2), ($3), ($4);", tableName) @@ -513,7 +512,7 @@ func GetPostgresSQLParamToolInfo(tableName string) (string, string, string, stri return createStatement, insertStatement, toolStatement, idParamStatement, nameParamStatement, arrayToolStatement, params } -// GetPostgresSQLAuthToolInfo returns statements and param of my-auth-tool for postgres-sql kind +// GetPostgresSQLAuthToolInfo returns statements and param of my-auth-tool for postgres-sql type func GetPostgresSQLAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id SERIAL PRIMARY KEY, name TEXT, email TEXT);", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name, email) VALUES ($1, $2), ($3, $4)", tableName) @@ -522,14 +521,14 @@ func GetPostgresSQLAuthToolInfo(tableName string) (string, string, string, []any return createStatement, insertStatement, toolStatement, params } -// GetPostgresSQLTmplToolStatement returns statements and param for template parameter test cases for postgres-sql kind +// GetPostgresSQLTmplToolStatement returns statements and param for template parameter test cases for postgres-sql type func GetPostgresSQLTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = $1" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = $1" return tmplSelectCombined, tmplSelectFilterCombined } -// GetMSSQLParamToolInfo returns statements and param for my-tool mssql-sql kind +// GetMSSQLParamToolInfo returns statements and param for my-tool mssql-sql type func GetMSSQLParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT IDENTITY(1,1) PRIMARY KEY, name VARCHAR(255));", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name) VALUES (@alice), (@jane), (@sid), (@nil);", tableName) @@ -541,7 +540,7 @@ func GetMSSQLParamToolInfo(tableName string) (string, string, string, string, st return createStatement, insertStatement, toolStatement, idParamStatement, nameParamStatement, arrayToolStatement, params } -// GetMSSQLAuthToolInfo returns statements and param of my-auth-tool for mssql-sql kind +// GetMSSQLAuthToolInfo returns statements and param of my-auth-tool for mssql-sql type func GetMSSQLAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT IDENTITY(1,1) PRIMARY KEY, name VARCHAR(255), email VARCHAR(255));", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name, email) VALUES (@alice, @aliceemail), (@jane, @janeemail);", tableName) @@ -550,14 +549,14 @@ func GetMSSQLAuthToolInfo(tableName string) (string, string, string, []any) { return createStatement, insertStatement, toolStatement, params } -// GetMSSQLTmplToolStatement returns statements and param for template parameter test cases for mysql-sql kind +// GetMSSQLTmplToolStatement returns statements and param for template parameter test cases for mysql-sql type func GetMSSQLTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = @id" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = @name" return tmplSelectCombined, tmplSelectFilterCombined } -// GetMySQLParamToolInfo returns statements and param for my-tool mysql-sql kind +// GetMySQLParamToolInfo returns statements and param for my-tool mysql-sql type func GetMySQLParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255));", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name) VALUES (?), (?), (?), (?);", tableName) @@ -569,7 +568,7 @@ func GetMySQLParamToolInfo(tableName string) (string, string, string, string, st return createStatement, insertStatement, toolStatement, idParamStatement, nameParamStatement, arrayToolStatement, params } -// GetMySQLAuthToolInfo returns statements and param of my-auth-tool for mysql-sql kind +// GetMySQLAuthToolInfo returns statements and param of my-auth-tool for mysql-sql type func GetMySQLAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255));", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name, email) VALUES (?, ?), (?, ?)", tableName) @@ -578,7 +577,7 @@ func GetMySQLAuthToolInfo(tableName string) (string, string, string, []any) { return createStatement, insertStatement, toolStatement, params } -// GetMySQLTmplToolStatement returns statements and param for template parameter test cases for mysql-sql kind +// GetMySQLTmplToolStatement returns statements and param for template parameter test cases for mysql-sql type func GetMySQLTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ?" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ?" @@ -711,26 +710,26 @@ func GetRedisValkeyWants() (string, string, string, string, string, string, stri return select1Want, mcpMyFailToolWant, invokeParamWant, invokeIdNullWant, nullWant, mcpSelect1Want, mcpInvokeParamWant } -func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map[string]any { +func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolType string) map[string]any { toolsFile := map[string]any{ "sources": map[string]any{ "my-instance": sourceConfig, }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "commands": [][]string{{"PING"}}, }, "my-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "commands": [][]string{{"HGETALL", "row1"}, {"HGETALL", "row3"}}, @@ -748,7 +747,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-tool-by-id": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "commands": [][]string{{"HGETALL", "row4"}}, @@ -761,7 +760,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-tool-by-name": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "commands": [][]string{{"GET", "null"}}, @@ -775,7 +774,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-array-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with array params.", "commands": [][]string{{"HGETALL", "row1"}, {"$cmdArray"}}, @@ -793,7 +792,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-auth-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", // statement to auto-fill authenticated parameter @@ -813,7 +812,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-auth-required-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "commands": [][]string{{"PING"}}, @@ -822,7 +821,7 @@ func GetRedisValkeyToolsConfig(sourceConfig map[string]any, toolKind string) map }, }, "my-fail-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test statement with incorrect syntax.", "commands": [][]string{{"SELEC 1;"}}, @@ -843,20 +842,20 @@ func TestCloudSQLMySQL_IPTypeParsingFromYAML(t *testing.T) { { desc: "IPType Defaulting to Public", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + database: my_db + user: my_user + password: my_pass `, want: server.SourceConfigs{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -870,21 +869,21 @@ func TestCloudSQLMySQL_IPTypeParsingFromYAML(t *testing.T) { { desc: "IPType Explicit Public", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: Public - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: Public + database: my_db + user: my_user + password: my_pass `, want: server.SourceConfigs{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -898,21 +897,21 @@ func TestCloudSQLMySQL_IPTypeParsingFromYAML(t *testing.T) { { desc: "IPType Explicit Private", in: ` - sources: - my-mysql-instance: - kind: cloud-sql-mysql - project: my-project - region: my-region - instance: my-instance - ipType: private - database: my_db - user: my_user - password: my_pass + kind: sources + name: my-mysql-instance + type: cloud-sql-mysql + project: my-project + region: my-region + instance: my-instance + ipType: private + database: my_db + user: my_user + password: my_pass `, want: server.SourceConfigs{ "my-mysql-instance": cloudsqlmysql.Config{ Name: "my-mysql-instance", - Kind: cloudsqlmysql.SourceKind, + Type: cloudsqlmysql.SourceType, Project: "my-project", Region: "my-region", Instance: "my-instance", @@ -926,16 +925,12 @@ func TestCloudSQLMySQL_IPTypeParsingFromYAML(t *testing.T) { } for _, tc := range tcs { t.Run(tc.desc, func(t *testing.T) { - got := struct { - Sources server.SourceConfigs `yaml:"sources"` - }{} - // Parse contents - err := yaml.Unmarshal(testutils.FormatYaml(tc.in), &got) + got, _, _, _, _, _, err := server.UnmarshalResourceConfig(context.Background(), testutils.FormatYaml(tc.in)) if err != nil { t.Fatalf("unable to unmarshal: %s", err) } - if !cmp.Equal(tc.want, got.Sources) { - t.Fatalf("incorrect parse: diff (-want +got):\n%s", cmp.Diff(tc.want, got.Sources)) + if !cmp.Equal(tc.want, got) { + t.Fatalf("incorrect parse: diff (-want +got):\n%s", cmp.Diff(tc.want, got)) } }) } diff --git a/tests/couchbase/couchbase_integration_test.go b/tests/couchbase/couchbase_integration_test.go index fcb0493c327a..d78c71b82df1 100644 --- a/tests/couchbase/couchbase_integration_test.go +++ b/tests/couchbase/couchbase_integration_test.go @@ -30,8 +30,8 @@ import ( ) const ( - couchbaseSourceKind = "couchbase" - couchbaseToolKind = "couchbase-sql" + couchbaseSourceType = "couchbase" + couchbaseToolType = "couchbase-sql" ) var ( @@ -58,7 +58,7 @@ func getCouchbaseVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": couchbaseSourceKind, + "type": couchbaseSourceType, "connectionString": couchbaseConnection, "bucket": couchbaseBucket, "scope": couchbaseScope, @@ -118,8 +118,8 @@ func TestCouchbaseToolEndpoints(t *testing.T) { defer teardownCollection3(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, couchbaseToolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, couchbaseToolKind, tmplSelectCombined, tmplSelectFilterCombined, tmplSelectAll) + toolsFile := tests.GetToolsConfig(sourceConfig, couchbaseToolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, couchbaseToolType, tmplSelectCombined, tmplSelectFilterCombined, tmplSelectAll) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -231,7 +231,7 @@ func setupCouchbaseCollection(t *testing.T, ctx context.Context, cluster *gocb.C } } -// getCouchbaseParamToolInfo returns statements and params for my-tool couchbase-sql kind +// getCouchbaseParamToolInfo returns statements and params for my-tool couchbase-sql type func getCouchbaseParamToolInfo(collectionName string) (string, string, string, string, []map[string]any) { // N1QL uses positional or named parameters with $ prefix toolStatement := fmt.Sprintf("SELECT TONUMBER(meta().id) as id, "+ @@ -254,7 +254,7 @@ func getCouchbaseParamToolInfo(collectionName string) (string, string, string, s return toolStatement, idToolStatement, nameToolStatement, arrayToolStatemnt, params } -// getCouchbaseAuthToolInfo returns statements and param of my-auth-tool for couchbase-sql kind +// getCouchbaseAuthToolInfo returns statements and param of my-auth-tool for couchbase-sql type func getCouchbaseAuthToolInfo(collectionName string) (string, []map[string]any) { toolStatement := fmt.Sprintf("SELECT name FROM %s WHERE email = $email", collectionName) diff --git a/tests/dataform/dataform_integration_test.go b/tests/dataform/dataform_integration_test.go index c7218f1d02d1..d2359983592d 100644 --- a/tests/dataform/dataform_integration_test.go +++ b/tests/dataform/dataform_integration_test.go @@ -69,7 +69,7 @@ func TestDataformCompileTool(t *testing.T) { toolsFile := map[string]any{ "tools": map[string]any{ "my-dataform-compiler": map[string]any{ - "kind": "dataform-compile-local", + "type": "dataform-compile-local", "description": "Tool to compile dataform projects", }, }, diff --git a/tests/dataplex/dataplex_integration_test.go b/tests/dataplex/dataplex_integration_test.go index 4466a50cf82e..1dcd72aeb368 100644 --- a/tests/dataplex/dataplex_integration_test.go +++ b/tests/dataplex/dataplex_integration_test.go @@ -40,10 +40,10 @@ import ( ) var ( - DataplexSourceKind = "dataplex" - DataplexSearchEntriesToolKind = "dataplex-search-entries" - DataplexLookupEntryToolKind = "dataplex-lookup-entry" - DataplexSearchAspectTypesToolKind = "dataplex-search-aspect-types" + DataplexSourceType = "dataplex" + DataplexSearchEntriesToolType = "dataplex-search-entries" + DataplexLookupEntryToolType = "dataplex-lookup-entry" + DataplexSearchAspectTypesToolType = "dataplex-search-aspect-types" DataplexProject = os.Getenv("DATAPLEX_PROJECT") ) @@ -53,7 +53,7 @@ func getDataplexVars(t *testing.T) map[string]any { t.Fatal("'DATAPLEX_PROJECT' not set") } return map[string]any{ - "kind": DataplexSourceKind, + "type": DataplexSourceType, "project": DataplexProject, } } @@ -283,40 +283,40 @@ func getDataplexToolsConfig(sourceConfig map[string]any) map[string]any { }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-dataplex-search-entries-tool": map[string]any{ - "kind": DataplexSearchEntriesToolKind, + "type": DataplexSearchEntriesToolType, "source": "my-dataplex-instance", "description": "Simple dataplex search entries tool to test end to end functionality.", }, "my-auth-dataplex-search-entries-tool": map[string]any{ - "kind": DataplexSearchEntriesToolKind, + "type": DataplexSearchEntriesToolType, "source": "my-dataplex-instance", "description": "Simple dataplex search entries tool to test end to end functionality.", "authRequired": []string{"my-google-auth"}, }, "my-dataplex-lookup-entry-tool": map[string]any{ - "kind": DataplexLookupEntryToolKind, + "type": DataplexLookupEntryToolType, "source": "my-dataplex-instance", "description": "Simple dataplex lookup entry tool to test end to end functionality.", }, "my-auth-dataplex-lookup-entry-tool": map[string]any{ - "kind": DataplexLookupEntryToolKind, + "type": DataplexLookupEntryToolType, "source": "my-dataplex-instance", "description": "Simple dataplex lookup entry tool to test end to end functionality.", "authRequired": []string{"my-google-auth"}, }, "my-dataplex-search-aspect-types-tool": map[string]any{ - "kind": DataplexSearchAspectTypesToolKind, + "type": DataplexSearchAspectTypesToolType, "source": "my-dataplex-instance", "description": "Simple dataplex search aspect types tool to test end to end functionality.", }, "my-auth-dataplex-search-aspect-types-tool": map[string]any{ - "kind": DataplexSearchAspectTypesToolKind, + "type": DataplexSearchAspectTypesToolType, "source": "my-dataplex-instance", "description": "Simple dataplex search aspect types tool to test end to end functionality.", "authRequired": []string{"my-google-auth"}, diff --git a/tests/dgraph/dgraph_integration_test.go b/tests/dgraph/dgraph_integration_test.go index f27cd8dab1eb..17e17358ba02 100644 --- a/tests/dgraph/dgraph_integration_test.go +++ b/tests/dgraph/dgraph_integration_test.go @@ -31,7 +31,7 @@ import ( ) var ( - DgraphSourceKind = "dgraph" + DgraphSourceType = "dgraph" DgraphApiKey = "api-key" DgraphUrl = os.Getenv("DGRAPH_URL") ) @@ -41,7 +41,7 @@ func getDgraphVars(t *testing.T) map[string]any { t.Fatal("'DGRAPH_URL' not set") } return map[string]any{ - "kind": DgraphSourceKind, + "type": DgraphSourceType, "dgraphUrl": DgraphUrl, "apiKey": DgraphApiKey, } @@ -61,7 +61,7 @@ func TestDgraphToolEndpoints(t *testing.T) { }, "tools": map[string]any{ "my-simple-dql-tool": map[string]any{ - "kind": "dgraph-dql", + "type": "dgraph-dql", "source": "my-dgraph-instance", "description": "Simple tool to test end to end functionality.", "statement": "{result(func: uid(0x0)) {constant: math(1)}}", diff --git a/tests/elasticsearch/elasticsearch_integration_test.go b/tests/elasticsearch/elasticsearch_integration_test.go index 16a7b39b7b63..bd451339c591 100644 --- a/tests/elasticsearch/elasticsearch_integration_test.go +++ b/tests/elasticsearch/elasticsearch_integration_test.go @@ -31,8 +31,8 @@ import ( ) var ( - ElasticsearchSourceKind = "elasticsearch" - ElasticsearchToolKind = "elasticsearch-esql" + ElasticsearchSourceType = "elasticsearch" + ElasticsearchToolType = "elasticsearch-esql" EsAddress = os.Getenv("ELASTICSEARCH_HOST") EsUser = os.Getenv("ELASTICSEARCH_USER") EsPass = os.Getenv("ELASTICSEARCH_PASS") @@ -43,7 +43,7 @@ func getElasticsearchVars(t *testing.T) map[string]any { t.Fatal("'ELASTICSEARCH_HOST' not set") } return map[string]any{ - "kind": ElasticsearchSourceKind, + "type": ElasticsearchSourceType, "addresses": []string{EsAddress}, "username": EsUser, "password": EsPass, @@ -72,7 +72,7 @@ func TestElasticsearchToolEndpoints(t *testing.T) { paramToolStatement, idParamToolStatement, nameParamToolStatement, arrayParamToolStatement, authToolStatement := getElasticsearchQueries(index) - toolsConfig := getElasticsearchToolsConfig(sourceConfig, ElasticsearchToolKind, paramToolStatement, idParamToolStatement, nameParamToolStatement, arrayParamToolStatement, authToolStatement) + toolsConfig := getElasticsearchToolsConfig(sourceConfig, ElasticsearchToolType, paramToolStatement, idParamToolStatement, nameParamToolStatement, arrayParamToolStatement, authToolStatement) cmd, cleanup, err := tests.StartCmd(ctx, toolsConfig, args...) if err != nil { @@ -177,26 +177,26 @@ func getElasticsearchWants() ElasticsearchWants { } } -func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { +func getElasticsearchToolsConfig(sourceConfig map[string]any, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { toolsFile := map[string]any{ "sources": map[string]any{ "my-instance": sourceConfig, }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "query": "FROM test-index | SORT id ASC", }, "my-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "query": paramToolStatement, @@ -214,7 +214,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-tool-by-id": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "query": idParamToolStmt, @@ -227,7 +227,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-tool-by-name": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "query": nameParamToolStmt, @@ -241,7 +241,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-array-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with array params.", "query": arrayToolStatement, @@ -269,7 +269,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-auth-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", // statement to auto-fill authenticated parameter @@ -289,7 +289,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-auth-required-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "query": "FROM test-index | SORT id ASC", @@ -298,7 +298,7 @@ func getElasticsearchToolsConfig(sourceConfig map[string]any, toolKind, paramToo }, }, "my-fail-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test statement with incorrect syntax.", "query": "SELEC 1;", diff --git a/tests/firebird/firebird_integration_test.go b/tests/firebird/firebird_integration_test.go index af0246d11ce5..256b6e7e66a2 100644 --- a/tests/firebird/firebird_integration_test.go +++ b/tests/firebird/firebird_integration_test.go @@ -32,8 +32,8 @@ import ( ) var ( - FirebirdSourceKind = "firebird" - FirebirdToolKind = "firebird-sql" + FirebirdSourceType = "firebird" + FirebirdToolType = "firebird-sql" FirebirdDatabase = os.Getenv("FIREBIRD_DATABASE") FirebirdHost = os.Getenv("FIREBIRD_HOST") FirebirdPort = os.Getenv("FIREBIRD_PORT") @@ -56,7 +56,7 @@ func getFirebirdVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": FirebirdSourceKind, + "type": FirebirdSourceType, "host": FirebirdHost, "port": FirebirdPort, "database": FirebirdDatabase, @@ -107,10 +107,10 @@ func TestFirebirdToolEndpoints(t *testing.T) { teardownTable2 := setupFirebirdTable(t, ctx, db, createAuthTableStmts, insertAuthTableStmt, tableNameAuth, authTestParams) defer teardownTable2(t) - toolsFile := getFirebirdToolsConfig(sourceConfig, FirebirdToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := getFirebirdToolsConfig(sourceConfig, FirebirdToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addFirebirdExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getFirebirdTmplToolStatement() - toolsFile = addFirebirdTemplateParamConfig(t, toolsFile, FirebirdToolKind, tmplSelectCombined, tmplSelectFilterCombined) + toolsFile = addFirebirdTemplateParamConfig(t, toolsFile, FirebirdToolType, tmplSelectCombined, tmplSelectFilterCombined) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -311,8 +311,8 @@ func getFirebirdWants() (string, string, string, string) { return select1Want, mcpMyFailToolWant, createTableStatement, mcpSelect1Want } -func getFirebirdToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { - toolsFile := tests.GetToolsConfig(sourceConfig, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) +func getFirebirdToolsConfig(sourceConfig map[string]any, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { + toolsFile := tests.GetToolsConfig(sourceConfig, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) toolsMap, ok := toolsFile["tools"].(map[string]any) if !ok { @@ -350,7 +350,7 @@ func getFirebirdToolsConfig(sourceConfig map[string]any, toolKind, paramToolStat return toolsFile } -func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKind, tmplSelectCombined, tmplSelectFilterCombined string) map[string]any { +func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolType, tmplSelectCombined, tmplSelectFilterCombined string) map[string]any { toolsMap, ok := config["tools"].(map[string]any) if !ok { t.Fatalf("unable to get tools from config") @@ -358,7 +358,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin // Firebird-specific template parameter tools with compatible syntax toolsMap["create-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Create table tool with template parameters", "statement": "CREATE TABLE {{.tableName}} ({{array .columns}})", @@ -368,7 +368,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin }, } toolsMap["insert-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Insert table tool with template parameters", "statement": "INSERT INTO {{.tableName}} ({{array .columns}}) VALUES ({{.values}})", @@ -379,7 +379,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin }, } toolsMap["select-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with template parameters", "statement": "SELECT id AS \"id\", name AS \"name\", age AS \"age\" FROM {{.tableName}}", @@ -388,7 +388,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin }, } toolsMap["select-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with combined template parameters", "statement": tmplSelectCombined, @@ -400,7 +400,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin }, } toolsMap["select-fields-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select specific fields tool with template parameters", "statement": "SELECT name AS \"name\" FROM {{.tableName}}", @@ -409,7 +409,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin }, } toolsMap["select-filter-templateParams-combined-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Select table tool with filter template parameters", "statement": tmplSelectFilterCombined, @@ -423,7 +423,7 @@ func addFirebirdTemplateParamConfig(t *testing.T, config map[string]any, toolKin } // Firebird uses simple DROP TABLE syntax without IF EXISTS toolsMap["drop-table-templateParams-tool"] = map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Drop table tool with template parameters", "statement": "DROP TABLE {{.tableName}}", @@ -441,12 +441,12 @@ func addFirebirdExecuteSqlConfig(t *testing.T, config map[string]any) map[string t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "firebird-execute-sql", + "type": "firebird-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "firebird-execute-sql", + "type": "firebird-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ diff --git a/tests/firestore/firestore_integration_test.go b/tests/firestore/firestore_integration_test.go index 5b1610e01afd..53bf90f657c8 100644 --- a/tests/firestore/firestore_integration_test.go +++ b/tests/firestore/firestore_integration_test.go @@ -37,7 +37,7 @@ import ( ) var ( - FirestoreSourceKind = "firestore" + FirestoreSourceType = "firestore" FirestoreProject = os.Getenv("FIRESTORE_PROJECT") FirestoreDatabase = os.Getenv("FIRESTORE_DATABASE") // Optional, defaults to "(default)" ) @@ -48,7 +48,7 @@ func getFirestoreVars(t *testing.T) map[string]any { } vars := map[string]any{ - "kind": FirestoreSourceKind, + "type": FirestoreSourceType, "project": FirestoreProject, } @@ -527,45 +527,45 @@ func getFirestoreToolsConfig(sourceConfig map[string]any) map[string]any { tools := map[string]any{ // Tool for RunToolGetTest "my-simple-tool": map[string]any{ - "kind": "firestore-get-documents", + "type": "firestore-get-documents", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, // Tool for MCP test - this will get documents "my-param-tool": map[string]any{ - "kind": "firestore-get-documents", + "type": "firestore-get-documents", "source": "my-instance", "description": "Tool to get documents by paths", }, // Tool for MCP test that fails "my-fail-tool": map[string]any{ - "kind": "firestore-get-documents", + "type": "firestore-get-documents", "source": "my-instance", "description": "Tool that will fail", }, // Firestore specific tools "firestore-get-docs": map[string]any{ - "kind": "firestore-get-documents", + "type": "firestore-get-documents", "source": "my-instance", "description": "Get multiple documents from Firestore", }, "firestore-list-colls": map[string]any{ - "kind": "firestore-list-collections", + "type": "firestore-list-collections", "source": "my-instance", "description": "List Firestore collections", }, "firestore-delete-docs": map[string]any{ - "kind": "firestore-delete-documents", + "type": "firestore-delete-documents", "source": "my-instance", "description": "Delete documents from Firestore", }, "firestore-query-coll": map[string]any{ - "kind": "firestore-query-collection", + "type": "firestore-query-collection", "source": "my-instance", "description": "Query a Firestore collection", }, "firestore-query-param": map[string]any{ - "kind": "firestore-query", + "type": "firestore-query", "source": "my-instance", "description": "Query a Firestore collection with parameterizable filters", "collectionPath": "{{.collection}}", @@ -595,7 +595,7 @@ func getFirestoreToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "firestore-query-select-array": map[string]any{ - "kind": "firestore-query", + "type": "firestore-query", "source": "my-instance", "description": "Query with array-based select fields", "collectionPath": "{{.collection}}", @@ -622,22 +622,22 @@ func getFirestoreToolsConfig(sourceConfig map[string]any) map[string]any { }, }, "firestore-get-rules": map[string]any{ - "kind": "firestore-get-rules", + "type": "firestore-get-rules", "source": "my-instance", "description": "Get Firestore security rules", }, "firestore-validate-rules": map[string]any{ - "kind": "firestore-validate-rules", + "type": "firestore-validate-rules", "source": "my-instance", "description": "Validate Firestore security rules", }, "firestore-add-docs": map[string]any{ - "kind": "firestore-add-documents", + "type": "firestore-add-documents", "source": "my-instance", "description": "Add documents to Firestore", }, "firestore-update-doc": map[string]any{ - "kind": "firestore-update-document", + "type": "firestore-update-document", "source": "my-instance", "description": "Update a document in Firestore", }, diff --git a/tests/http/http_integration_test.go b/tests/http/http_integration_test.go index dcaab030111f..eb928f3d8d33 100644 --- a/tests/http/http_integration_test.go +++ b/tests/http/http_integration_test.go @@ -34,8 +34,8 @@ import ( ) var ( - HttpSourceKind = "http" - HttpToolKind = "http" + HttpSourceType = "http" + HttpToolType = "http" ) func getHTTPSourceConfig(t *testing.T) map[string]any { @@ -46,7 +46,7 @@ func getHTTPSourceConfig(t *testing.T) map[string]any { idToken = "Bearer " + idToken return map[string]any{ - "kind": HttpSourceKind, + "type": HttpSourceType, "headers": map[string]string{"Authorization": idToken}, } } @@ -309,7 +309,7 @@ func TestHttpToolEndpoints(t *testing.T) { var args []string - toolsFile := getHTTPToolsConfig(sourceConfig, HttpToolKind) + toolsFile := getHTTPToolsConfig(sourceConfig, HttpToolType) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { t.Fatalf("command initialization returned an error: %s", err) @@ -475,7 +475,7 @@ func runAdvancedHTTPInvokeTest(t *testing.T) { } // getHTTPToolsConfig returns a mock HTTP tool's config file -func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string]any { +func getHTTPToolsConfig(sourceConfig map[string]any, toolType string) map[string]any { // Write config into a file and pass it to command otherSourceConfig := make(map[string]any) for k, v := range sourceConfig { @@ -491,13 +491,13 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "path": "/tool0", "method": "POST", "source": "my-instance", @@ -505,7 +505,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string "description": "Simple tool to test end to end functionality.", }, "my-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "GET", "path": "/tool1", @@ -521,7 +521,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string "headers": map[string]string{"Content-Type": "application/json"}, }, "my-tool-by-id": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "GET", "path": "/tool1id", @@ -531,7 +531,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string "headers": map[string]string{"Content-Type": "application/json"}, }, "my-tool-by-name": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "GET", "path": "/tool1name", @@ -541,7 +541,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string "headers": map[string]string{"Content-Type": "application/json"}, }, "my-query-param-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "GET", "path": "/toolQueryTest", @@ -553,7 +553,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string }, }, "my-auth-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "GET", "path": "/tool2", @@ -565,7 +565,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string }, }, "my-auth-required-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "method": "POST", "path": "/tool0", @@ -574,7 +574,7 @@ func getHTTPToolsConfig(sourceConfig map[string]any, toolKind string) map[string "authRequired": []string{"my-google-auth"}, }, "my-advanced-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "other-instance", "method": "get", "path": "/{{.path}}?id=2", diff --git a/tests/looker/looker_integration_test.go b/tests/looker/looker_integration_test.go index c360455907d4..944cbcb9265c 100644 --- a/tests/looker/looker_integration_test.go +++ b/tests/looker/looker_integration_test.go @@ -36,7 +36,7 @@ import ( ) var ( - LookerSourceKind = "looker" + LookerSourceType = "looker" LookerBaseUrl = os.Getenv("LOOKER_BASE_URL") LookerVerifySsl = os.Getenv("LOOKER_VERIFY_SSL") LookerClientId = os.Getenv("LOOKER_CLIENT_ID") @@ -62,7 +62,7 @@ func getLookerVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": LookerSourceKind, + "type": LookerSourceType, "base_url": LookerBaseUrl, "verify_ssl": (LookerVerifySsl == "true"), "client_id": LookerClientId, @@ -93,162 +93,162 @@ func TestLooker(t *testing.T) { }, "tools": map[string]any{ "get_models": map[string]any{ - "kind": "looker-get-models", + "type": "looker-get-models", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_explores": map[string]any{ - "kind": "looker-get-explores", + "type": "looker-get-explores", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_dimensions": map[string]any{ - "kind": "looker-get-dimensions", + "type": "looker-get-dimensions", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_measures": map[string]any{ - "kind": "looker-get-measures", + "type": "looker-get-measures", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_filters": map[string]any{ - "kind": "looker-get-filters", + "type": "looker-get-filters", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_parameters": map[string]any{ - "kind": "looker-get-parameters", + "type": "looker-get-parameters", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "query": map[string]any{ - "kind": "looker-query", + "type": "looker-query", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "query_sql": map[string]any{ - "kind": "looker-query-sql", + "type": "looker-query-sql", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "query_url": map[string]any{ - "kind": "looker-query-url", + "type": "looker-query-url", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_looks": map[string]any{ - "kind": "looker-get-looks", + "type": "looker-get-looks", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "make_look": map[string]any{ - "kind": "looker-make-look", + "type": "looker-make-look", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_dashboards": map[string]any{ - "kind": "looker-get-dashboards", + "type": "looker-get-dashboards", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "make_dashboard": map[string]any{ - "kind": "looker-make-dashboard", + "type": "looker-make-dashboard", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "add_dashboard_filter": map[string]any{ - "kind": "looker-add-dashboard-filter", + "type": "looker-add-dashboard-filter", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "add_dashboard_element": map[string]any{ - "kind": "looker-add-dashboard-element", + "type": "looker-add-dashboard-element", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "conversational_analytics": map[string]any{ - "kind": "looker-conversational-analytics", + "type": "looker-conversational-analytics", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "health_pulse": map[string]any{ - "kind": "looker-health-pulse", + "type": "looker-health-pulse", "source": "my-instance", "description": "Checks the health of a Looker instance by running a series of checks on the system.", }, "health_analyze": map[string]any{ - "kind": "looker-health-analyze", + "type": "looker-health-analyze", "source": "my-instance", "description": "Provides analysis of a Looker instance's projects, models, or explores.", }, "health_vacuum": map[string]any{ - "kind": "looker-health-vacuum", + "type": "looker-health-vacuum", "source": "my-instance", "description": "Vacuums unused content from a Looker instance.", }, "dev_mode": map[string]any{ - "kind": "looker-dev-mode", + "type": "looker-dev-mode", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_projects": map[string]any{ - "kind": "looker-get-projects", + "type": "looker-get-projects", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_project_files": map[string]any{ - "kind": "looker-get-project-files", + "type": "looker-get-project-files", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_project_file": map[string]any{ - "kind": "looker-get-project-file", + "type": "looker-get-project-file", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "create_project_file": map[string]any{ - "kind": "looker-create-project-file", + "type": "looker-create-project-file", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "update_project_file": map[string]any{ - "kind": "looker-update-project-file", + "type": "looker-update-project-file", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "delete_project_file": map[string]any{ - "kind": "looker-delete-project-file", + "type": "looker-delete-project-file", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "generate_embed_url": map[string]any{ - "kind": "looker-generate-embed-url", + "type": "looker-generate-embed-url", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_connections": map[string]any{ - "kind": "looker-get-connections", + "type": "looker-get-connections", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_connection_schemas": map[string]any{ - "kind": "looker-get-connection-schemas", + "type": "looker-get-connection-schemas", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_connection_databases": map[string]any{ - "kind": "looker-get-connection-databases", + "type": "looker-get-connection-databases", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_connection_tables": map[string]any{ - "kind": "looker-get-connection-tables", + "type": "looker-get-connection-tables", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, "get_connection_table_columns": map[string]any{ - "kind": "looker-get-connection-table-columns", + "type": "looker-get-connection-table-columns", "source": "my-instance", "description": "Simple tool to test end to end functionality.", }, diff --git a/tests/mariadb/mariadb_integration_test.go b/tests/mariadb/mariadb_integration_test.go index 60d734ace73e..df3f4fb60c18 100644 --- a/tests/mariadb/mariadb_integration_test.go +++ b/tests/mariadb/mariadb_integration_test.go @@ -36,8 +36,8 @@ import ( ) var ( - MariaDBSourceKind = "mysql" - MariaDBToolKind = "mysql-sql" + MariaDBSourceType = "mysql" + MariaDBToolType = "mysql-sql" MariaDBDatabase = os.Getenv("MARIADB_DATABASE") MariaDBHost = os.Getenv("MARIADB_HOST") MariaDBPort = os.Getenv("MARIADB_PORT") @@ -60,7 +60,7 @@ func getMariaDBVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": MariaDBSourceKind, + "type": MariaDBSourceType, "host": MariaDBHost, "port": MariaDBPort, "database": MariaDBDatabase, @@ -112,10 +112,10 @@ func TestMySQLToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, MariaDBToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, MariaDBToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddMySqlExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMySQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MariaDBToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MariaDBToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddMySQLPrebuiltToolConfig(t, toolsFile) diff --git a/tests/mindsdb/mindsdb_integration_test.go b/tests/mindsdb/mindsdb_integration_test.go index cbebce8238ce..18a8cb71f84e 100644 --- a/tests/mindsdb/mindsdb_integration_test.go +++ b/tests/mindsdb/mindsdb_integration_test.go @@ -33,8 +33,8 @@ import ( ) var ( - MindsDBSourceKind = "mindsdb" - MindsDBToolKind = "mindsdb-sql" + MindsDBSourceType = "mindsdb" + MindsDBToolType = "mindsdb-sql" MindsDBDatabase = os.Getenv("MINDSDB_DATABASE") MindsDBHost = os.Getenv("MINDSDB_HOST") MindsDBPort = os.Getenv("MINDSDB_PORT") @@ -66,7 +66,7 @@ func getMindsDBVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": MindsDBSourceKind, + "type": MindsDBSourceType, "host": MindsDBHost, "port": MindsDBPort, "database": MindsDBDatabase, @@ -107,19 +107,19 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "statement": "SELECT 1", }, "my-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": paramToolStmt, @@ -137,7 +137,7 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, }, "my-tool-by-id": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": idParamToolStmt, @@ -150,7 +150,7 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, }, "my-tool-by-name": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test invocation with params.", "statement": nameParamToolStmt, @@ -164,13 +164,13 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, }, "my-array-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test invocation with array params.", "statement": "SELECT 1 as id, 'Alice' as name UNION SELECT 3 as id, 'Sid' as name", }, "my-auth-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", "statement": authToolStmt, @@ -189,7 +189,7 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, }, "my-auth-required-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "statement": "SELECT 1", @@ -198,18 +198,18 @@ func TestMindsDBToolEndpoints(t *testing.T) { }, }, "my-fail-tool": map[string]any{ - "kind": MindsDBToolKind, + "type": MindsDBToolType, "source": "my-instance", "description": "Tool to test statement with incorrect syntax.", "statement": "INVALID SQL STATEMENT", }, "my-exec-sql-tool": map[string]any{ - "kind": "mindsdb-execute-sql", + "type": "mindsdb-execute-sql", "source": "my-instance", "description": "Tool to execute sql", }, "my-auth-exec-sql-tool": map[string]any{ - "kind": "mindsdb-execute-sql", + "type": "mindsdb-execute-sql", "source": "my-instance", "description": "Tool to execute sql with auth", "authRequired": []string{ diff --git a/tests/mongodb/mongodb_integration_test.go b/tests/mongodb/mongodb_integration_test.go index 3d84837de8ae..b3675dbd32f5 100644 --- a/tests/mongodb/mongodb_integration_test.go +++ b/tests/mongodb/mongodb_integration_test.go @@ -33,8 +33,8 @@ import ( ) var ( - MongoDbSourceKind = "mongodb" - MongoDbToolKind = "mongodb-find" + MongoDbSourceType = "mongodb" + MongoDbToolType = "mongodb-find" MongoDbUri = os.Getenv("MONGODB_URI") MongoDbDatabase = os.Getenv("MONGODB_DATABASE") ServiceAccountEmail = os.Getenv("SERVICE_ACCOUNT_EMAIL") @@ -48,7 +48,7 @@ func getMongoDBVars(t *testing.T) map[string]any { t.Fatal("'MongoDbDatabase' not set") } return map[string]any{ - "kind": MongoDbSourceKind, + "type": MongoDbSourceType, "uri": MongoDbUri, } } @@ -83,7 +83,7 @@ func TestMongoDBToolEndpoints(t *testing.T) { defer teardownDB(t) // Write config into a file and pass it to command - toolsFile := getMongoDBToolsConfig(sourceConfig, MongoDbToolKind) + toolsFile := getMongoDBToolsConfig(sourceConfig, MongoDbToolType) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -482,20 +482,20 @@ func setupMongoDB(t *testing.T, ctx context.Context, database *mongo.Database) f } -func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[string]any { +func getMongoDBToolsConfig(sourceConfig map[string]any, toolType string) map[string]any { toolsFile := map[string]any{ "sources": map[string]any{ "my-instance": sourceConfig, }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": "mongodb-find-one", + "type": "mongodb-find-one", "source": "my-instance", "description": "Simple tool to test end to end functionality.", "collection": "test_collection", @@ -505,7 +505,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "authRequired": []string{}, @@ -528,7 +528,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-tool-by-id": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "authRequired": []string{}, @@ -546,7 +546,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-tool-by-name": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with params.", "authRequired": []string{}, @@ -565,7 +565,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-array-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test invocation with array.", "authRequired": []string{}, @@ -587,7 +587,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-auth-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test authenticated parameters.", "authRequired": []string{}, @@ -611,7 +611,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-auth-required-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test auth required invocation.", "authRequired": []string{ @@ -624,7 +624,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-fail-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Tool to test statement with incorrect syntax.", "authRequired": []string{}, @@ -635,7 +635,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "limit": 10, }, "my-delete-one-tool": map[string]any{ - "kind": "mongodb-delete-one", + "type": "mongodb-delete-one", "source": "my-instance", "description": "Tool to test deleting an entry.", "authRequired": []string{}, @@ -645,7 +645,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-delete-many-tool": map[string]any{ - "kind": "mongodb-delete-many", + "type": "mongodb-delete-many", "source": "my-instance", "description": "Tool to test deleting multiple entries.", "authRequired": []string{}, @@ -655,7 +655,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-insert-one-tool": map[string]any{ - "kind": "mongodb-insert-one", + "type": "mongodb-insert-one", "source": "my-instance", "description": "Tool to test inserting an entry.", "authRequired": []string{}, @@ -664,7 +664,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-insert-many-tool": map[string]any{ - "kind": "mongodb-insert-many", + "type": "mongodb-insert-many", "source": "my-instance", "description": "Tool to test inserting multiple entries.", "authRequired": []string{}, @@ -673,7 +673,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-update-one-tool": map[string]any{ - "kind": "mongodb-update-one", + "type": "mongodb-update-one", "source": "my-instance", "description": "Tool to test updating an entry.", "authRequired": []string{}, @@ -698,7 +698,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-update-many-tool": map[string]any{ - "kind": "mongodb-update-many", + "type": "mongodb-update-many", "source": "my-instance", "description": "Tool to test updating multiple entries.", "authRequired": []string{}, @@ -723,7 +723,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-aggregate-tool": map[string]any{ - "kind": "mongodb-aggregate", + "type": "mongodb-aggregate", "source": "my-instance", "description": "Tool to test an aggregation.", "authRequired": []string{}, @@ -740,7 +740,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-read-only-aggregate-tool": map[string]any{ - "kind": "mongodb-aggregate", + "type": "mongodb-aggregate", "source": "my-instance", "description": "Tool to test an aggregation.", "authRequired": []string{}, @@ -758,7 +758,7 @@ func getMongoDBToolsConfig(sourceConfig map[string]any, toolKind string) map[str "database": MongoDbDatabase, }, "my-read-write-aggregate-tool": map[string]any{ - "kind": "mongodb-aggregate", + "type": "mongodb-aggregate", "source": "my-instance", "description": "Tool to test an aggregation.", "authRequired": []string{}, diff --git a/tests/mssql/mssql_integration_test.go b/tests/mssql/mssql_integration_test.go index b9dbe4712a0a..d3430f5a04b1 100644 --- a/tests/mssql/mssql_integration_test.go +++ b/tests/mssql/mssql_integration_test.go @@ -32,8 +32,8 @@ import ( ) var ( - MSSQLSourceKind = "mssql" - MSSQLToolKind = "mssql-sql" + MSSQLSourceType = "mssql" + MSSQLToolType = "mssql-sql" MSSQLDatabase = os.Getenv("MSSQL_DATABASE") MSSQLHost = os.Getenv("MSSQL_HOST") MSSQLPort = os.Getenv("MSSQL_PORT") @@ -56,7 +56,7 @@ func getMsSQLVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": MSSQLSourceKind, + "type": MSSQLSourceType, "host": MSSQLHost, "port": MSSQLPort, "database": MSSQLDatabase, @@ -116,10 +116,10 @@ func TestMSSQLToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, MSSQLToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, MSSQLToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddMSSQLExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMSSQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MSSQLToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MSSQLToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddMSSQLPrebuiltToolConfig(t, toolsFile) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) diff --git a/tests/mysql/mysql_integration_test.go b/tests/mysql/mysql_integration_test.go index 113767fd1d21..3f9558181fee 100644 --- a/tests/mysql/mysql_integration_test.go +++ b/tests/mysql/mysql_integration_test.go @@ -30,8 +30,8 @@ import ( ) var ( - MySQLSourceKind = "mysql" - MySQLToolKind = "mysql-sql" + MySQLSourceType = "mysql" + MySQLToolType = "mysql-sql" MySQLDatabase = os.Getenv("MYSQL_DATABASE") MySQLHost = os.Getenv("MYSQL_HOST") MySQLPort = os.Getenv("MYSQL_PORT") @@ -54,7 +54,7 @@ func getMySQLVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": MySQLSourceKind, + "type": MySQLSourceType, "host": MySQLHost, "port": MySQLPort, "database": MySQLDatabase, @@ -106,10 +106,10 @@ func TestMySQLToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, MySQLToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, MySQLToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddMySqlExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMySQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MySQLToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, MySQLToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddMySQLPrebuiltToolConfig(t, toolsFile) diff --git a/tests/neo4j/neo4j_integration_test.go b/tests/neo4j/neo4j_integration_test.go index 5f2f357b4fd8..a9d41babcc5a 100644 --- a/tests/neo4j/neo4j_integration_test.go +++ b/tests/neo4j/neo4j_integration_test.go @@ -34,7 +34,7 @@ import ( ) var ( - Neo4jSourceKind = "neo4j" + Neo4jSourceType = "neo4j" Neo4jDatabase = os.Getenv("NEO4J_DATABASE") Neo4jUri = os.Getenv("NEO4J_URI") Neo4jUser = os.Getenv("NEO4J_USER") @@ -56,7 +56,7 @@ func getNeo4jVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": Neo4jSourceKind, + "type": Neo4jSourceType, "uri": Neo4jUri, "database": Neo4jDatabase, "user": Neo4jUser, @@ -81,35 +81,35 @@ func TestNeo4jToolEndpoints(t *testing.T) { }, "tools": map[string]any{ "my-simple-cypher-tool": map[string]any{ - "kind": "neo4j-cypher", + "type": "neo4j-cypher", "source": "my-neo4j-instance", "description": "Simple tool to test end to end functionality.", "statement": "RETURN 1 as a;", }, "my-simple-execute-cypher-tool": map[string]any{ - "kind": "neo4j-execute-cypher", + "type": "neo4j-execute-cypher", "source": "my-neo4j-instance", "description": "Simple tool to test end to end functionality.", }, "my-readonly-execute-cypher-tool": map[string]any{ - "kind": "neo4j-execute-cypher", + "type": "neo4j-execute-cypher", "source": "my-neo4j-instance", "description": "A readonly cypher execution tool.", "readOnly": true, }, "my-schema-tool": map[string]any{ - "kind": "neo4j-schema", + "type": "neo4j-schema", "source": "my-neo4j-instance", "description": "A tool to get the Neo4j schema.", }, "my-schema-tool-with-cache": map[string]any{ - "kind": "neo4j-schema", + "type": "neo4j-schema", "source": "my-neo4j-instance", "description": "A schema tool with a custom cache expiration.", "cacheExpireMinutes": 10, }, "my-populated-schema-tool": map[string]any{ - "kind": "neo4j-schema", + "type": "neo4j-schema", "source": "my-neo4j-instance", "description": "A tool to get the Neo4j schema from a populated DB.", }, diff --git a/tests/oceanbase/oceanbase_integration_test.go b/tests/oceanbase/oceanbase_integration_test.go index e7691808fbb0..c81f96db0770 100644 --- a/tests/oceanbase/oceanbase_integration_test.go +++ b/tests/oceanbase/oceanbase_integration_test.go @@ -32,8 +32,8 @@ import ( ) var ( - OceanBaseSourceKind = "oceanbase" - OceanBaseToolKind = "oceanbase-sql" + OceanBaseSourceType = "oceanbase" + OceanBaseToolType = "oceanbase-sql" OceanBaseDatabase = os.Getenv("OCEANBASE_DATABASE") OceanBaseHost = os.Getenv("OCEANBASE_HOST") OceanBasePort = os.Getenv("OCEANBASE_PORT") @@ -56,7 +56,7 @@ func getOceanBaseVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": OceanBaseSourceKind, + "type": OceanBaseSourceType, "host": OceanBaseHost, "port": OceanBasePort, "database": OceanBaseDatabase, @@ -105,10 +105,10 @@ func TestOceanBaseToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, OceanBaseToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, OceanBaseToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addOceanBaseExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getOceanBaseTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, OceanBaseToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, OceanBaseToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -179,12 +179,12 @@ func addOceanBaseExecuteSqlConfig(t *testing.T, config map[string]any) map[strin t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "oceanbase-execute-sql", + "type": "oceanbase-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "oceanbase-execute-sql", + "type": "oceanbase-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ diff --git a/tests/oracle/oracle_integration_test.go b/tests/oracle/oracle_integration_test.go index 0021679e9e46..75f5fc00de18 100644 --- a/tests/oracle/oracle_integration_test.go +++ b/tests/oracle/oracle_integration_test.go @@ -18,8 +18,8 @@ import ( ) var ( - OracleSourceKind = "oracle" - OracleToolKind = "oracle-sql" + OracleSourceType = "oracle" + OracleToolType = "oracle-sql" OracleHost = os.Getenv("ORACLE_HOST") OracleUser = os.Getenv("ORACLE_USER") OraclePass = os.Getenv("ORACLE_PASS") @@ -41,7 +41,7 @@ func getOracleVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": OracleSourceKind, + "type": OracleSourceType, "connectionString": OracleConnStr, "useOCI": true, "user": OracleUser, @@ -98,10 +98,10 @@ func TestOracleSimpleToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, OracleToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, OracleToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddExecuteSqlConfig(t, toolsFile, "oracle-execute-sql") tmplSelectCombined, tmplSelectFilterCombined := tests.GetMySQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, OracleToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, OracleToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/postgres/postgres_integration_test.go b/tests/postgres/postgres_integration_test.go index ea34a4a8bcd5..06cb19310d06 100644 --- a/tests/postgres/postgres_integration_test.go +++ b/tests/postgres/postgres_integration_test.go @@ -31,8 +31,8 @@ import ( ) var ( - PostgresSourceKind = "postgres" - PostgresToolKind = "postgres-sql" + PostgresSourceType = "postgres" + PostgresToolType = "postgres-sql" PostgresDatabase = os.Getenv("POSTGRES_DATABASE") PostgresHost = os.Getenv("POSTGRES_HOST") PostgresPort = os.Getenv("POSTGRES_PORT") @@ -55,7 +55,7 @@ func getPostgresVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": PostgresSourceKind, + "type": PostgresSourceType, "host": PostgresHost, "port": PostgresPort, "database": PostgresDatabase, @@ -116,15 +116,15 @@ func TestPostgres(t *testing.T) { defer tearDownVectorTable(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, PostgresToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, PostgresToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = tests.AddExecuteSqlConfig(t, toolsFile, "postgres-execute-sql") tmplSelectCombined, tmplSelectFilterCombined := tests.GetPostgresSQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, PostgresToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, PostgresToolType, tmplSelectCombined, tmplSelectFilterCombined, "") toolsFile = tests.AddPostgresPrebuiltConfig(t, toolsFile) // Add semantic search tool config insertStmt, searchStmt := tests.GetPostgresVectorSearchStmts(vectorTableName) - toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, PostgresToolKind, insertStmt, searchStmt) + toolsFile = tests.AddSemanticSearchConfig(t, toolsFile, PostgresToolType, insertStmt, searchStmt) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/redis/redis_test.go b/tests/redis/redis_test.go index 6ee611da5161..1fdace25aef2 100644 --- a/tests/redis/redis_test.go +++ b/tests/redis/redis_test.go @@ -28,8 +28,8 @@ import ( ) var ( - RedisSourceKind = "redis" - RedisToolKind = "redis" + RedisSourceType = "redis" + RedisToolType = "redis" RedisAddress = os.Getenv("REDIS_ADDRESS") RedisPass = os.Getenv("REDIS_PASS") ) @@ -42,7 +42,7 @@ func getRedisVars(t *testing.T) map[string]any { t.Fatal("'REDIS_PASS' not set") } return map[string]any{ - "kind": RedisSourceKind, + "type": RedisSourceType, "address": []string{RedisAddress}, "password": RedisPass, } @@ -81,7 +81,7 @@ func TestRedisToolEndpoints(t *testing.T) { defer teardownDB(t) // Write config into a file and pass it to command - toolsFile := tests.GetRedisValkeyToolsConfig(sourceConfig, RedisToolKind) + toolsFile := tests.GetRedisValkeyToolsConfig(sourceConfig, RedisToolType) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/serverlessspark/serverless_spark_integration_test.go b/tests/serverlessspark/serverless_spark_integration_test.go index 12545a87aa52..5ac8df1b1b27 100644 --- a/tests/serverlessspark/serverless_spark_integration_test.go +++ b/tests/serverlessspark/serverless_spark_integration_test.go @@ -64,7 +64,7 @@ func getServerlessSparkVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": "serverless-spark", + "type": "serverless-spark", "project": serverlessSparkProject, "location": serverlessSparkLocation, } @@ -81,40 +81,40 @@ func TestServerlessSparkToolEndpoints(t *testing.T) { }, "authServices": map[string]any{ "my-google-auth": map[string]any{ - "kind": "google", + "type": "google", "clientId": tests.ClientId, }, }, "tools": map[string]any{ "list-batches": map[string]any{ - "kind": "serverless-spark-list-batches", + "type": "serverless-spark-list-batches", "source": "my-spark", }, "list-batches-with-auth": map[string]any{ - "kind": "serverless-spark-list-batches", + "type": "serverless-spark-list-batches", "source": "my-spark", "authRequired": []string{"my-google-auth"}, }, "get-batch": map[string]any{ - "kind": "serverless-spark-get-batch", + "type": "serverless-spark-get-batch", "source": "my-spark", }, "get-batch-with-auth": map[string]any{ - "kind": "serverless-spark-get-batch", + "type": "serverless-spark-get-batch", "source": "my-spark", "authRequired": []string{"my-google-auth"}, }, "cancel-batch": map[string]any{ - "kind": "serverless-spark-cancel-batch", + "type": "serverless-spark-cancel-batch", "source": "my-spark", }, "cancel-batch-with-auth": map[string]any{ - "kind": "serverless-spark-cancel-batch", + "type": "serverless-spark-cancel-batch", "source": "my-spark", "authRequired": []string{"my-google-auth"}, }, "create-pyspark-batch": map[string]any{ - "kind": "serverless-spark-create-pyspark-batch", + "type": "serverless-spark-create-pyspark-batch", "source": "my-spark", "environmentConfig": map[string]any{ "executionConfig": map[string]any{ @@ -123,7 +123,7 @@ func TestServerlessSparkToolEndpoints(t *testing.T) { }, }, "create-pyspark-batch-2-3": map[string]any{ - "kind": "serverless-spark-create-pyspark-batch", + "type": "serverless-spark-create-pyspark-batch", "source": "my-spark", "runtimeConfig": map[string]any{"version": "2.3"}, "environmentConfig": map[string]any{ @@ -133,12 +133,12 @@ func TestServerlessSparkToolEndpoints(t *testing.T) { }, }, "create-pyspark-batch-with-auth": map[string]any{ - "kind": "serverless-spark-create-pyspark-batch", + "type": "serverless-spark-create-pyspark-batch", "source": "my-spark", "authRequired": []string{"my-google-auth"}, }, "create-spark-batch": map[string]any{ - "kind": "serverless-spark-create-spark-batch", + "type": "serverless-spark-create-spark-batch", "source": "my-spark", "environmentConfig": map[string]any{ "executionConfig": map[string]any{ @@ -147,7 +147,7 @@ func TestServerlessSparkToolEndpoints(t *testing.T) { }, }, "create-spark-batch-2-3": map[string]any{ - "kind": "serverless-spark-create-spark-batch", + "type": "serverless-spark-create-spark-batch", "source": "my-spark", "runtimeConfig": map[string]any{"version": "2.3"}, "environmentConfig": map[string]any{ @@ -157,7 +157,7 @@ func TestServerlessSparkToolEndpoints(t *testing.T) { }, }, "create-spark-batch-with-auth": map[string]any{ - "kind": "serverless-spark-create-spark-batch", + "type": "serverless-spark-create-spark-batch", "source": "my-spark", "authRequired": []string{"my-google-auth"}, }, diff --git a/tests/singlestore/singlestore_integration_test.go b/tests/singlestore/singlestore_integration_test.go index 28419d49f354..5ada56d6f519 100644 --- a/tests/singlestore/singlestore_integration_test.go +++ b/tests/singlestore/singlestore_integration_test.go @@ -30,8 +30,8 @@ import ( ) var ( - SingleStoreSourceKind = "singlestore" - SingleStoreToolKind = "singlestore-sql" + SingleStoreSourceType = "singlestore" + SingleStoreToolType = "singlestore-sql" SingleStoreDatabase = os.Getenv("SINGLESTORE_DATABASE") SingleStoreHost = os.Getenv("SINGLESTORE_HOST") SingleStorePort = os.Getenv("SINGLESTORE_PORT") @@ -54,7 +54,7 @@ func getSingleStoreVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": SingleStoreSourceKind, + "type": SingleStoreSourceType, "host": SingleStoreHost, "port": SingleStorePort, "database": SingleStoreDatabase, @@ -85,7 +85,7 @@ func getSingleStoreAuthToolInfo(tableName string) (string, string, string, []any return createStatement, insertStatement, toolStatement, params } -// getSingleStoreTmplToolStatement returns statements and param for template parameter test cases for singlestore-sql kind +// getSingleStoreTmplToolStatement returns statements and param for template parameter test cases for singlestore-sql type func getSingleStoreTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ?" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ?" @@ -130,8 +130,8 @@ func setupSingleStoreTable(t *testing.T, ctx context.Context, pool *sql.DB, crea } } -func getSingleStoreToolsConfig(sourceConfig map[string]any, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { - toolsFile := tests.GetToolsConfig(sourceConfig, toolKind, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) +func getSingleStoreToolsConfig(sourceConfig map[string]any, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement string) map[string]any { + toolsFile := tests.GetToolsConfig(sourceConfig, toolType, paramToolStatement, idParamToolStmt, nameParamToolStmt, arrayToolStatement, authToolStatement) toolsMap, ok := toolsFile["tools"].(map[string]any) if !ok { @@ -151,12 +151,12 @@ func addSingleStoreExecuteSQLConfig(t *testing.T, config map[string]any) map[str t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "singlestore-execute-sql", + "type": "singlestore-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "singlestore-execute-sql", + "type": "singlestore-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -207,10 +207,10 @@ func TestSingleStoreToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := getSingleStoreToolsConfig(sourceConfig, SingleStoreToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := getSingleStoreToolsConfig(sourceConfig, SingleStoreToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addSingleStoreExecuteSQLConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getSingleStoreTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SingleStoreToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SingleStoreToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/snowflake/snowflake_integration_test.go b/tests/snowflake/snowflake_integration_test.go index cd81c8289f60..ee07a8610757 100644 --- a/tests/snowflake/snowflake_integration_test.go +++ b/tests/snowflake/snowflake_integration_test.go @@ -31,8 +31,8 @@ import ( ) var ( - SnowflakeSourceKind = "snowflake" - SnowflakeToolKind = "snowflake-sql" + SnowflakeSourceType = "snowflake" + SnowflakeToolType = "snowflake-sql" SnowflakeAccount = os.Getenv("SNOWFLAKE_ACCOUNT") SnowflakeUser = os.Getenv("SNOWFLAKE_USER") SnowflakePassword = os.Getenv("SNOWFLAKE_PASS") @@ -65,7 +65,7 @@ func getSnowflakeVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": SnowflakeSourceKind, + "type": SnowflakeSourceType, "account": SnowflakeAccount, "user": SnowflakeUser, "password": SnowflakePassword, @@ -125,10 +125,10 @@ func TestSnowflake(t *testing.T) { t.Logf("Test table setup complete.") // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, SnowflakeToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, SnowflakeToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addSnowflakeExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getSnowflakeTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SnowflakeToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SnowflakeToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -173,13 +173,13 @@ func addSnowflakeExecuteSqlConfig(t *testing.T, config map[string]any) map[strin } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "snowflake-execute-sql", + "type": "snowflake-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "snowflake-execute-sql", + "type": "snowflake-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -190,7 +190,7 @@ func addSnowflakeExecuteSqlConfig(t *testing.T, config map[string]any) map[strin return config } -// getSnowflakeParamToolInfo returns statements and param for my-param-tool snowflake-sql kind +// getSnowflakeParamToolInfo returns statements and param for my-param-tool snowflake-sql type func getSnowflakeParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INTEGER AUTOINCREMENT PRIMARY KEY, name STRING);", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name) VALUES (?), (?), (?), (?);", tableName) @@ -202,7 +202,7 @@ func getSnowflakeParamToolInfo(tableName string) (string, string, string, string return createStatement, insertStatement, toolStatement, idParamStatement, nameParamStatement, arrayToolStatement, params } -// getSnowflakeAuthToolInfo returns statements and param of my-auth-tool for snowflake-sql kind +// getSnowflakeAuthToolInfo returns statements and param of my-auth-tool for snowflake-sql type func getSnowflakeAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INTEGER AUTOINCREMENT PRIMARY KEY, name STRING, email STRING);", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (name, email) VALUES (?, ?), (?, ?)", tableName) @@ -211,7 +211,7 @@ func getSnowflakeAuthToolInfo(tableName string) (string, string, string, []any) return createStatement, insertStatement, toolStatement, params } -// getSnowflakeTmplToolStatement returns statements and param for template parameter test cases for snowflake-sql kind +// getSnowflakeTmplToolStatement returns statements and param for template parameter test cases for snowflake-sql type func getSnowflakeTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ?" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ?" diff --git a/tests/source.go b/tests/source.go index 6ef647f823fd..6750dad490cf 100644 --- a/tests/source.go +++ b/tests/source.go @@ -30,7 +30,7 @@ import ( ) // RunSourceConnection test for source connection -func RunSourceConnectionTest(t *testing.T, sourceConfig map[string]any, toolKind string) error { +func RunSourceConnectionTest(t *testing.T, sourceConfig map[string]any, toolType string) error { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -43,7 +43,7 @@ func RunSourceConnectionTest(t *testing.T, sourceConfig map[string]any, toolKind }, "tools": map[string]any{ "my-simple-tool": map[string]any{ - "kind": toolKind, + "type": toolType, "source": "my-instance", "description": "Simple tool to test end to end functionality.", "statement": "SELECT 1;", diff --git a/tests/spanner/spanner_integration_test.go b/tests/spanner/spanner_integration_test.go index 4daf87a27ee2..265b84d89ea3 100644 --- a/tests/spanner/spanner_integration_test.go +++ b/tests/spanner/spanner_integration_test.go @@ -37,8 +37,8 @@ import ( ) var ( - SpannerSourceKind = "spanner" - SpannerToolKind = "spanner-sql" + SpannerSourceType = "spanner" + SpannerToolType = "spanner-sql" SpannerProject = os.Getenv("SPANNER_PROJECT") SpannerDatabase = os.Getenv("SPANNER_DATABASE") SpannerInstance = os.Getenv("SPANNER_INSTANCE") @@ -55,7 +55,7 @@ func getSpannerVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": SpannerSourceKind, + "type": SpannerSourceType, "project": SpannerProject, "instance": SpannerInstance, "database": SpannerDatabase, @@ -163,7 +163,7 @@ func TestSpannerToolEndpoints(t *testing.T) { defer teardownGraph(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, SpannerToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, SpannerToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addSpannerExecuteSqlConfig(t, toolsFile) toolsFile = addSpannerReadOnlyConfig(t, toolsFile) toolsFile = addTemplateParamConfig(t, toolsFile) @@ -215,7 +215,7 @@ func TestSpannerToolEndpoints(t *testing.T) { runSpannerListGraphsTest(t, graphName) } -// getSpannerToolInfo returns statements and param for my-tool for spanner-sql kind +// getSpannerToolInfo returns statements and param for my-tool for spanner-sql type func getSpannerParamToolInfo(tableName string) (string, string, string, string, string, string, map[string]any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT64, name STRING(MAX)) PRIMARY KEY (id)", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name) VALUES (1, @name1), (2, @name2), (3, @name3), (4, @name4)", tableName) @@ -227,7 +227,7 @@ func getSpannerParamToolInfo(tableName string) (string, string, string, string, return createStatement, insertStatement, toolStatement, idToolStatement, nameToolStatement, arrayToolStatement, params } -// getSpannerAuthToolInfo returns statements and param of my-auth-tool for spanner-sql kind +// getSpannerAuthToolInfo returns statements and param of my-auth-tool for spanner-sql type func getSpannerAuthToolInfo(tableName string) (string, string, string, map[string]any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id INT64, name STRING(MAX), email STRING(MAX)) PRIMARY KEY (id)", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name, email) VALUES (1, @name1, @email1), (2, @name2, @email2)", tableName) @@ -331,18 +331,18 @@ func addSpannerExecuteSqlConfig(t *testing.T, config map[string]any) map[string] t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool-read-only"] = map[string]any{ - "kind": "spanner-execute-sql", + "type": "spanner-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "readOnly": true, } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "spanner-execute-sql", + "type": "spanner-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "spanner-execute-sql", + "type": "spanner-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -359,14 +359,14 @@ func addSpannerReadOnlyConfig(t *testing.T, config map[string]any) map[string]an t.Fatalf("unable to get tools from config") } tools["access-schema-read-only"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Tool to access information schema in read-only mode.", "statement": "SELECT schema_name FROM `INFORMATION_SCHEMA`.SCHEMATA WHERE schema_name='INFORMATION_SCHEMA';", "readOnly": true, } tools["access-schema"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Tool to access information schema.", "statement": "SELECT schema_name FROM `INFORMATION_SCHEMA`.SCHEMATA WHERE schema_name='INFORMATION_SCHEMA';", @@ -384,7 +384,7 @@ func addSpannerListTablesConfig(t *testing.T, config map[string]any) map[string] // Add spanner-list-tables tool tools["list-tables-tool"] = map[string]any{ - "kind": "spanner-list-tables", + "type": "spanner-list-tables", "source": "my-instance", "description": "Lists tables with their schema information", } @@ -402,7 +402,7 @@ func addSpannerListGraphsConfig(t *testing.T, config map[string]any) map[string] // Add spanner-list-graphs tool tools["list-graphs-tool"] = map[string]any{ - "kind": "spanner-list-graphs", + "type": "spanner-list-graphs", "source": "my-instance", "description": "Lists graphs with their schema information", } @@ -417,7 +417,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any t.Fatalf("unable to get tools from config") } toolsMap["insert-table-templateParams-tool"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Insert tool with template parameters", "statement": "INSERT INTO {{.tableName}} ({{array .columns}}) VALUES ({{.values}})", @@ -428,7 +428,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-templateParams-tool"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT * FROM {{.tableName}}", @@ -437,7 +437,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-templateParams-combined-tool"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT * FROM {{.tableName}} WHERE id = @id", @@ -447,7 +447,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-fields-templateParams-tool"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT {{array .fields}} FROM {{.tableName}}", @@ -457,7 +457,7 @@ func addTemplateParamConfig(t *testing.T, config map[string]any) map[string]any }, } toolsMap["select-filter-templateParams-combined-tool"] = map[string]any{ - "kind": "spanner-sql", + "type": "spanner-sql", "source": "my-instance", "description": "Create table tool with template parameters", "statement": "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = @name", diff --git a/tests/sqlite/sqlite_integration_test.go b/tests/sqlite/sqlite_integration_test.go index 730e70f4f585..ac01cbd0ca59 100644 --- a/tests/sqlite/sqlite_integration_test.go +++ b/tests/sqlite/sqlite_integration_test.go @@ -32,14 +32,14 @@ import ( ) var ( - SQLiteSourceKind = "sqlite" - SQLiteToolKind = "sqlite-sql" + SQLiteSourceType = "sqlite" + SQLiteToolType = "sqlite-sql" SQLiteDatabase = os.Getenv("SQLITE_DATABASE") ) func getSQLiteVars(t *testing.T) map[string]any { return map[string]any{ - "kind": SQLiteSourceKind, + "type": SQLiteSourceType, "database": SQLiteDatabase, } } @@ -137,9 +137,9 @@ func TestSQLiteToolEndpoint(t *testing.T) { setupSQLiteTestDB(t, ctx, db, createAuthTableStmt, insertAuthTableStmt, tableNameAuth, authTestParams) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, SQLiteToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, SQLiteToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) tmplSelectCombined, tmplSelectFilterCombined := getSQLiteTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SQLiteToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, SQLiteToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { @@ -191,7 +191,7 @@ func TestSQLiteExecuteSqlTool(t *testing.T) { toolConfig := map[string]any{ "tools": map[string]any{ "my-exec-sql-tool": map[string]any{ - "kind": "sqlite-execute-sql", + "type": "sqlite-execute-sql", "source": "my-instance", "description": "Tool to execute SQL statements", }, diff --git a/tests/tidb/tidb_integration_test.go b/tests/tidb/tidb_integration_test.go index 29efca8f358b..8e9c5f6c7fb5 100644 --- a/tests/tidb/tidb_integration_test.go +++ b/tests/tidb/tidb_integration_test.go @@ -30,8 +30,8 @@ import ( ) var ( - TiDBSourceKind = "tidb" - TiDBToolKind = "tidb-sql" + TiDBSourceType = "tidb" + TiDBToolType = "tidb-sql" TiDBDatabase = os.Getenv("TIDB_DATABASE") TiDBHost = os.Getenv("TIDB_HOST") TiDBPort = os.Getenv("TIDB_PORT") @@ -54,7 +54,7 @@ func getTiDBVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": TiDBSourceKind, + "type": TiDBSourceType, "host": TiDBHost, "port": TiDBPort, "database": TiDBDatabase, @@ -91,12 +91,12 @@ func addTiDBExecuteSqlConfig(t *testing.T, config map[string]any) map[string]any t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "tidb-execute-sql", + "type": "tidb-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "tidb-execute-sql", + "type": "tidb-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -135,10 +135,10 @@ func TestTiDBToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, TiDBToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, TiDBToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addTiDBExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := tests.GetMySQLTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, TiDBToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, TiDBToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/trino/trino_integration_test.go b/tests/trino/trino_integration_test.go index 126e887b22d6..6006caf2bb8e 100644 --- a/tests/trino/trino_integration_test.go +++ b/tests/trino/trino_integration_test.go @@ -31,8 +31,8 @@ import ( ) var ( - TrinoSourceKind = "trino" - TrinoToolKind = "trino-sql" + TrinoSourceType = "trino" + TrinoToolType = "trino-sql" TrinoHost = os.Getenv("TRINO_HOST") TrinoPort = os.Getenv("TRINO_PORT") TrinoUser = os.Getenv("TRINO_USER") @@ -55,7 +55,7 @@ func getTrinoVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": TrinoSourceKind, + "type": TrinoSourceType, "host": TrinoHost, "port": TrinoPort, "user": TrinoUser, @@ -119,7 +119,7 @@ func buildTrinoDSN(host, port, user, password, catalog, schema, queryTimeout, ac return dsn, nil } -// getTrinoParamToolInfo returns statements and param for my-tool trino-sql kind +// getTrinoParamToolInfo returns statements and param for my-tool trino-sql type func getTrinoParamToolInfo(tableName string) (string, string, string, string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id BIGINT NOT NULL, name VARCHAR(255))", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name) VALUES (1, ?), (2, ?), (3, ?), (4, ?)", tableName) @@ -131,7 +131,7 @@ func getTrinoParamToolInfo(tableName string) (string, string, string, string, st return createStatement, insertStatement, toolStatement, idParamStatement, nameParamStatement, arrayToolStatement, params } -// getTrinoAuthToolInfo returns statements and param of my-auth-tool for trino-sql kind +// getTrinoAuthToolInfo returns statements and param of my-auth-tool for trino-sql type func getTrinoAuthToolInfo(tableName string) (string, string, string, []any) { createStatement := fmt.Sprintf("CREATE TABLE %s (id BIGINT NOT NULL, name VARCHAR(255), email VARCHAR(255))", tableName) insertStatement := fmt.Sprintf("INSERT INTO %s (id, name, email) VALUES (1, ?, ?), (2, ?, ?)", tableName) @@ -140,7 +140,7 @@ func getTrinoAuthToolInfo(tableName string) (string, string, string, []any) { return createStatement, insertStatement, toolStatement, params } -// getTrinoTmplToolStatement returns statements and param for template parameter test cases for trino-sql kind +// getTrinoTmplToolStatement returns statements and param for template parameter test cases for trino-sql type func getTrinoTmplToolStatement() (string, string) { tmplSelectCombined := "SELECT * FROM {{.tableName}} WHERE id = ?" tmplSelectFilterCombined := "SELECT * FROM {{.tableName}} WHERE {{.columnFilter}} = ?" @@ -192,12 +192,12 @@ func addTrinoExecuteSqlConfig(t *testing.T, config map[string]any) map[string]an t.Fatalf("unable to get tools from config") } tools["my-exec-sql-tool"] = map[string]any{ - "kind": "trino-execute-sql", + "type": "trino-execute-sql", "source": "my-instance", "description": "Tool to execute sql", } tools["my-auth-exec-sql-tool"] = map[string]any{ - "kind": "trino-execute-sql", + "type": "trino-execute-sql", "source": "my-instance", "description": "Tool to execute sql", "authRequired": []string{ @@ -236,10 +236,10 @@ func TestTrinoToolEndpoints(t *testing.T) { defer teardownTable2(t) // Write config into a file and pass it to command - toolsFile := tests.GetToolsConfig(sourceConfig, TrinoToolKind, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) + toolsFile := tests.GetToolsConfig(sourceConfig, TrinoToolType, paramToolStmt, idParamToolStmt, nameParamToolStmt, arrayToolStmt, authToolStmt) toolsFile = addTrinoExecuteSqlConfig(t, toolsFile) tmplSelectCombined, tmplSelectFilterCombined := getTrinoTmplToolStatement() - toolsFile = tests.AddTemplateParamConfig(t, toolsFile, TrinoToolKind, tmplSelectCombined, tmplSelectFilterCombined, "") + toolsFile = tests.AddTemplateParamConfig(t, toolsFile, TrinoToolType, tmplSelectCombined, tmplSelectFilterCombined, "") cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/utility/wait_integration_test.go b/tests/utility/wait_integration_test.go index c7891592c212..9485b4ea4070 100644 --- a/tests/utility/wait_integration_test.go +++ b/tests/utility/wait_integration_test.go @@ -37,7 +37,7 @@ func RunWaitTool(t *testing.T) { toolsFile := map[string]any{ "tools": map[string]any{ "my-wait-for-tool": map[string]any{ - "kind": "wait", + "type": "wait", "description": "Wait for a specified duration.", "timeout": "30s", }, diff --git a/tests/valkey/valkey_test.go b/tests/valkey/valkey_test.go index 23f2b09df217..a159694bdd44 100644 --- a/tests/valkey/valkey_test.go +++ b/tests/valkey/valkey_test.go @@ -28,8 +28,8 @@ import ( ) var ( - ValkeySourceKind = "valkey" - ValkeyToolKind = "valkey" + ValkeySourceType = "valkey" + ValkeyToolType = "valkey" ValkeyAddress = os.Getenv("VALKEY_ADDRESS") ) @@ -39,7 +39,7 @@ func getValkeyVars(t *testing.T) map[string]any { t.Fatal("'VALKEY_ADDRESS' not set") } return map[string]any{ - "kind": ValkeySourceKind, + "type": ValkeySourceType, "address": []string{ValkeyAddress}, "disableCache": true, } @@ -84,7 +84,7 @@ func TestValkeyToolEndpoints(t *testing.T) { defer teardownDB(t) // Write config into a file and pass it to command - toolsFile := tests.GetRedisValkeyToolsConfig(sourceConfig, ValkeyToolKind) + toolsFile := tests.GetRedisValkeyToolsConfig(sourceConfig, ValkeyToolType) cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...) if err != nil { diff --git a/tests/yugabytedb/yugabytedb_integration_test.go b/tests/yugabytedb/yugabytedb_integration_test.go index 04483f3d131a..60dcb6cd6e41 100644 --- a/tests/yugabytedb/yugabytedb_integration_test.go +++ b/tests/yugabytedb/yugabytedb_integration_test.go @@ -58,7 +58,7 @@ func getYBVars(t *testing.T) map[string]any { } return map[string]any{ - "kind": YBDB_SOURCE_KIND, + "type": YBDB_SOURCE_KIND, "host": YBDB_HOST, "port": YBDB_PORT, "database": YBDB_DATABASE,