Skip to content

Commit 5b50f4e

Browse files
chore: added integration tests and improved some logic base on integration tests
1 parent 9bbfd93 commit 5b50f4e

File tree

7 files changed

+121
-44
lines changed

7 files changed

+121
-44
lines changed

docs/en/integrations/looker/tools/looker-create-agent.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ source: my-looker-instance
3636
description: |
3737
Create a new Looker agent.
3838
- `name` (string): The name of the agent.
39+
- `description` (string): The description of the agent.
3940
- `instructions` (string): The instructions (system prompt) for the agent.
4041
- `sources` (array): Optional. A list of JSON-encoded data sources for the agent (e.g., `[{"model": "my_model", "explore": "my_explore"}]`).
4142
- `code_interpreter` (boolean): Optional. Enables Code Interpreter for this Agent.

docs/en/integrations/looker/tools/looker-update-agent.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ description: |
3737
Update a Looker agent.
3838
- `agent_id` (string): The ID of the agent.
3939
- `name` (string): The name of the agent.
40+
- `description` (string): The description of the agent.
4041
- `instructions` (string): The instructions (system prompt) for the agent.
4142
- `sources` (array): Optional. A list of JSON-encoded data sources for the agent (e.g., `[{"model": "my_model", "explore": "my_explore"}]`).
4243
- `code_interpreter` (boolean): Optional. Enables Code Interpreter for this Agent.

internal/tools/looker/lookercreateagent/lookercreateagent.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func (cfg Config) ToolConfigType() string {
7070

7171
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
7272
nameParameter := parameters.NewStringParameterWithDefault("name", "", "The name of the agent.")
73+
descriptionParameter := parameters.NewStringParameterWithDefault("description", "", "The description of the agent.")
7374
instructionsParameter := parameters.NewStringParameterWithDefault("instructions", "", "The instructions (system prompt) for the agent.")
7475
sourcesParameter := parameters.NewArrayParameterWithRequired(
7576
"sources",
@@ -82,7 +83,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
8283
),
8384
)
8485
codeInterpreterParameter := parameters.NewBooleanParameterWithDefault("code_interpreter", false, "Optional. Enables Code Interpreter for this Agent.")
85-
params := parameters.Parameters{nameParameter, instructionsParameter, sourcesParameter, codeInterpreterParameter}
86+
params := parameters.Parameters{nameParameter, descriptionParameter, instructionsParameter, sourcesParameter, codeInterpreterParameter}
8687

8788
annotations := &tools.ToolAnnotations{}
8889
if cfg.Annotations != nil {
@@ -138,24 +139,26 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
138139
mapParams := params.AsMap()
139140
logger.DebugContext(ctx, fmt.Sprintf("%s params = ", t.Name), mapParams)
140141

141-
var name, instructions string
142+
var name, description, instructions string
142143
if v, ok := mapParams["name"].(string); ok {
143144
name = v
144145
}
146+
if v, ok := mapParams["description"].(string); ok {
147+
description = v
148+
}
145149
if v, ok := mapParams["instructions"].(string); ok {
146150
instructions = v
147151
}
148152

149153
agentSources := make([]v4.Source, 0)
150-
if _, ok := mapParams["sources"]; ok {
151-
sources, _ := mapParams["sources"].([]map[string]string)
152-
154+
if sources, ok := mapParams["sources"].([]any); ok {
153155
for _, s := range sources {
154-
model, ok := s["model"]
156+
source := s.(map[string]any)
157+
model, ok := source["model"].(string)
155158
if !ok {
156159
return nil, util.NewClientServerError("invalid source format: expected model of type string", http.StatusBadRequest, nil)
157160
}
158-
explore, ok := s["explore"]
161+
explore, ok := source["explore"].(string)
159162
if !ok {
160163
return nil, util.NewClientServerError("invalid source format: expected explore of type string", http.StatusBadRequest, nil)
161164
}
@@ -164,6 +167,8 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
164167
Explore: &explore,
165168
})
166169
}
170+
} else {
171+
return nil, util.NewClientServerError(fmt.Sprintf("invalid sources. got %T, expected []any", mapParams["sources"]), http.StatusBadRequest, nil)
167172
}
168173

169174
codeInterpreter, hasCodeInterpreter := mapParams["code_interpreter"].(bool)
@@ -174,10 +179,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
174179
body := v4.WriteAgent{
175180
Name: &name,
176181
}
182+
if description != "" {
183+
body.Description = &description
184+
}
177185
if instructions != "" {
178-
body.Context = &v4.Context{
186+
context := v4.Context{
179187
Instructions: &instructions,
180188
}
189+
body.Context = &context
181190
}
182191
if len(agentSources) > 0 {
183192
body.Sources = &agentSources

internal/tools/looker/lookercreateagent/lookercreateagent_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,23 @@ func TestInvokeValidation(t *testing.T) {
164164
wantErr string
165165
}{
166166
{
167-
desc: "missing name",
168-
params: parameters.ParamValues{},
167+
desc: "missing name",
168+
params: parameters.ParamValues{
169+
{Name: "description", Value: "description test"},
170+
{Name: "sources", Value: []any{
171+
map[string]any{"model": "test", "explore": "test"},
172+
}},
173+
},
169174
wantErr: "name must be specified",
170175
},
171176
{
172177
desc: "invalid source format",
173178
params: parameters.ParamValues{
174179
{Name: "name", Value: "test"},
175-
{Name: "sources", Value: []map[string]string{{"foo": "test", "bar": "test"}}},
180+
{Name: "description", Value: "description test"},
181+
{Name: "sources", Value: []any{
182+
map[string]any{"model": 123, "explore": "test"},
183+
}},
176184
},
177185
wantErr: "invalid source format: expected model of type string",
178186
},

internal/tools/looker/lookerupdateagent/lookerupdateagent.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (cfg Config) ToolConfigType() string {
7171
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
7272
agentIdParameter := parameters.NewStringParameterWithDefault("agent_id", "", "The ID of the agent.")
7373
nameParameter := parameters.NewStringParameterWithDefault("name", "", "The name of the agent.")
74+
descriptionParameter := parameters.NewStringParameterWithDefault("description", "", "The description of the agent.")
7475
instructionsParameter := parameters.NewStringParameterWithDefault("instructions", "", "The instructions (system prompt) for the agent.")
7576
sourcesParameter := parameters.NewArrayParameterWithRequired(
7677
"sources",
@@ -83,7 +84,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
8384
),
8485
)
8586
codeInterpreterParameter := parameters.NewBooleanParameterWithDefault("code_interpreter", false, "Optional. Enables Code Interpreter for this Agent.")
86-
params := parameters.Parameters{agentIdParameter, nameParameter, instructionsParameter, sourcesParameter, codeInterpreterParameter}
87+
params := parameters.Parameters{agentIdParameter, nameParameter, descriptionParameter, instructionsParameter, sourcesParameter, codeInterpreterParameter}
8788

8889
annotations := &tools.ToolAnnotations{}
8990
if cfg.Annotations != nil {
@@ -139,29 +140,35 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
139140
mapParams := params.AsMap()
140141
logger.DebugContext(ctx, fmt.Sprintf("%s params = ", t.Name), mapParams)
141142

142-
var agentId, name, instructions string
143+
var agentId, name, description, instructions string
143144
if v, ok := mapParams["agent_id"].(string); ok {
144145
agentId = v
145146
}
146147
if v, ok := mapParams["name"].(string); ok {
147148
name = v
148149
}
150+
if v, ok := mapParams["description"].(string); ok {
151+
description = v
152+
}
149153
if v, ok := mapParams["instructions"].(string); ok {
150154
instructions = v
151155
}
152156

157+
codeInterpreter, hasCodeInterpreter := mapParams["code_interpreter"].(bool)
158+
159+
if agentId == "" {
160+
return nil, util.NewClientServerError(fmt.Sprintf("%s operation: agent_id must be specified", t.Type), http.StatusBadRequest, nil)
161+
}
162+
153163
agentSources := make([]v4.Source, 0)
154-
if _, ok := mapParams["sources"]; ok {
155-
sources, _ := mapParams["sources"].([]map[string]string)
156-
if !ok {
157-
return nil, util.NewClientServerError("invalid source format: expected sources of type []map[string]string", http.StatusBadRequest, nil)
158-
}
164+
if sources, ok := mapParams["sources"].([]any); ok {
159165
for _, s := range sources {
160-
model, ok := s["model"]
166+
source := s.(map[string]any)
167+
model, ok := source["model"].(string)
161168
if !ok {
162169
return nil, util.NewClientServerError("invalid source format: expected model of type string", http.StatusBadRequest, nil)
163170
}
164-
explore, ok := s["explore"]
171+
explore, ok := source["explore"].(string)
165172
if !ok {
166173
return nil, util.NewClientServerError("invalid source format: expected explore of type string", http.StatusBadRequest, nil)
167174
}
@@ -170,17 +177,19 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
170177
Explore: &explore,
171178
})
172179
}
180+
} else {
181+
if _, ok := mapParams["sources"]; ok {
182+
return nil, util.NewClientServerError(fmt.Sprintf("invalid sources. got %T, expected []any", mapParams["sources"]), http.StatusBadRequest, nil)
183+
}
173184
}
174185

175-
codeInterpreter, hasCodeInterpreter := mapParams["code_interpreter"].(bool)
176-
177-
if agentId == "" {
178-
return nil, util.NewClientServerError(fmt.Sprintf("%s operation: agent_id must be specified", t.Type), http.StatusBadRequest, nil)
179-
}
180186
body := v4.WriteAgent{}
181187
if name != "" {
182188
body.Name = &name
183189
}
190+
if description != "" {
191+
body.Description = &description
192+
}
184193
if instructions != "" {
185194
body.Context = &v4.Context{
186195
Instructions: &instructions,

internal/tools/looker/lookerupdateagent/lookerupdateagent_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ func TestInvokeValidation(t *testing.T) {
172172
desc: "invalid source format",
173173
params: parameters.ParamValues{
174174
{Name: "agent_id", Value: "test"},
175-
{Name: "sources", Value: []map[string]string{{"foo": "test", "bar": "test"}}},
175+
{Name: "sources", Value: []any{
176+
map[string]any{"model": 123, "explore": "test"},
177+
}},
176178
},
177179
wantErr: "invalid source format: expected model of type string",
178180
},

tests/looker/looker_integration_test.go

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,31 @@ func TestLooker(t *testing.T) {
293293
"source": "my-instance",
294294
"description": "Simple tool to test end to end functionality.",
295295
},
296+
"list_agents": map[string]any{
297+
"type": "looker-list-agents",
298+
"source": "my-instance",
299+
"description": "Simple tool to test end to end functionality.",
300+
},
301+
"get_agent": map[string]any{
302+
"type": "looker-get-agent",
303+
"source": "my-instance",
304+
"description": "Simple tool to test end to end functionality.",
305+
},
306+
"create_agent": map[string]any{
307+
"type": "looker-create-agent",
308+
"source": "my-instance",
309+
"description": "Simple tool to test end to end functionality.",
310+
},
311+
"update_agent": map[string]any{
312+
"type": "looker-update-agent",
313+
"source": "my-instance",
314+
"description": "Simple tool to test end to end functionality.",
315+
},
316+
"delete_agent": map[string]any{
317+
"type": "looker-delete-agent",
318+
"source": "my-instance",
319+
"description": "Simple tool to test end to end functionality.",
320+
},
296321
},
297322
}
298323

@@ -1900,24 +1925,6 @@ func TestLooker(t *testing.T) {
19001925
wantResult = "null"
19011926
tests.RunToolInvokeParametersTest(t, "get_dashboards", []byte(`{"title": "FOO", "desc": "BAR"}`), wantResult)
19021927

1903-
wantResult = "\"Connection\":\"thelook\""
1904-
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_db_connections"}`), wantResult)
1905-
1906-
wantResult = "[]"
1907-
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_schedule_failures"}`), wantResult)
1908-
1909-
wantResult = "[{\"Feature\":\"Unsupported in Looker (Google Cloud core)\"}]"
1910-
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_legacy_features"}`), wantResult)
1911-
1912-
wantResult = "\"Project\":\"the_look\""
1913-
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "projects"}`), wantResult)
1914-
1915-
wantResult = "\"Model\":\"the_look\""
1916-
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "explores", "project": "the_look", "model": "the_look", "explore": "inventory_items"}`), wantResult)
1917-
1918-
wantResult = "\"Model\":\"the_look\""
1919-
tests.RunToolInvokeParametersTest(t, "health_vacuum", []byte(`{"action": "models"}`), wantResult)
1920-
19211928
wantResult = "the_look"
19221929
tests.RunToolInvokeSimpleTest(t, "get_projects", wantResult)
19231930

@@ -2001,6 +2008,28 @@ func TestLooker(t *testing.T) {
20012008
wantResult = "/login/embed?t=" // testing for specific substring, since url is dynamic
20022009
tests.RunToolInvokeParametersTest(t, "generate_embed_url", []byte(`{"type": "dashboards", "id": "1"}`), wantResult)
20032010

2011+
wantResult = fmt.Sprintf("agent_%s", randstr)
2012+
tests.RunToolInvokeParametersTest(t, "create_agent", []byte(fmt.Sprintf(`{"name": "agent_%s", "description": "test description", "instructions": "test instructions", "sources": [{"model": "the_look", "explore": "events"}]}`, randstr)), wantResult)
2013+
2014+
wantResult = fmt.Sprintf("agent_%s", randstr)
2015+
tests.RunToolInvokeParametersTest(t, "list_agents", []byte(`{}`), wantResult)
2016+
2017+
sdk := newLookerTestSDK(t)
2018+
reqSearchAgents := v4.RequestSearchAgents{
2019+
Name: &wantResult,
2020+
}
2021+
agents, _ := sdk.SearchAgents(reqSearchAgents, nil)
2022+
agentId := *agents[0].Id
2023+
2024+
wantResult = fmt.Sprintf("agent_%s", randstr)
2025+
tests.RunToolInvokeParametersTest(t, "get_agent", []byte(fmt.Sprintf(`{"agent_id": "%s"}`, agentId)), wantResult)
2026+
2027+
wantResult = fmt.Sprintf("agent_%s", randstr)
2028+
tests.RunToolInvokeParametersTest(t, "update_agent", []byte(fmt.Sprintf(`{"agent_id": "%s", "sources": [{"model": "system__activity", "explore": "history"}]}`, agentId)), wantResult)
2029+
2030+
wantResult = ""
2031+
tests.RunToolInvokeParametersTest(t, "delete_agent", []byte(fmt.Sprintf(`{"agent_id": "%s"}`, agentId)), wantResult)
2032+
20042033
runConversationalAnalytics(t, "system__activity", "content_usage")
20052034

20062035
deleteLook := testMakeLook(t, randstr)
@@ -2010,6 +2039,24 @@ func TestLooker(t *testing.T) {
20102039
defer deleteDashboard()
20112040
testAddDashboardFilter(t, dashboardId)
20122041
testAddDashboardElement(t, dashboardId)
2042+
2043+
wantResult = "\"Connection\":\"thelook\""
2044+
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_db_connections"}`), wantResult)
2045+
2046+
wantResult = "[]"
2047+
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_schedule_failures"}`), wantResult)
2048+
2049+
wantResult = "[{\"Feature\":\"Unsupported in Looker (Google Cloud core)\"}]"
2050+
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_legacy_features"}`), wantResult)
2051+
2052+
wantResult = "\"Project\":\"the_look\""
2053+
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "projects"}`), wantResult)
2054+
2055+
wantResult = "\"Model\":\"the_look\""
2056+
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "explores", "project": "the_look", "model": "the_look", "explore": "inventory_items"}`), wantResult)
2057+
2058+
wantResult = "\"Model\":\"the_look\""
2059+
tests.RunToolInvokeParametersTest(t, "health_vacuum", []byte(`{"action": "models"}`), wantResult)
20132060
}
20142061

20152062
func runConversationalAnalytics(t *testing.T, modelName, exploreName string) {

0 commit comments

Comments
 (0)