From a8e1b853ca73022f13dc91d30f1d8f069d341f60 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 20 Jun 2024 13:49:21 -0700 Subject: [PATCH] feat: add input filters --- pkg/engine/cmd.go | 3 +- pkg/engine/engine.go | 3 +- pkg/openai/client.go | 9 +- pkg/parser/parser.go | 11 ++- pkg/parser/parser_test.go | 24 +++++ pkg/runner/input.go | 27 ++++++ pkg/runner/runner.go | 34 +++++--- pkg/tests/runner_test.go | 21 +++++ .../testdata/TestInput/call1-resp.golden | 9 ++ pkg/tests/testdata/TestInput/call1.golden | 24 +++++ .../testdata/TestInput/call2-resp.golden | 9 ++ pkg/tests/testdata/TestInput/call2.golden | 42 +++++++++ pkg/tests/testdata/TestInput/step1.golden | 47 ++++++++++ pkg/tests/testdata/TestInput/step2.golden | 65 ++++++++++++++ pkg/tests/testdata/TestInput/test.gpt | 23 +++++ pkg/types/set.go | 2 +- pkg/types/tool.go | 87 ++++++++++++++----- pkg/types/tool_test.go | 46 +++++----- 18 files changed, 424 insertions(+), 62 deletions(-) create mode 100644 pkg/runner/input.go create mode 100644 pkg/tests/testdata/TestInput/call1-resp.golden create mode 100644 pkg/tests/testdata/TestInput/call1.golden create mode 100644 pkg/tests/testdata/TestInput/call2-resp.golden create mode 100644 pkg/tests/testdata/TestInput/call2.golden create mode 100644 pkg/tests/testdata/TestInput/step1.golden create mode 100644 pkg/tests/testdata/TestInput/step2.golden create mode 100644 pkg/tests/testdata/TestInput/test.gpt diff --git a/pkg/engine/cmd.go b/pkg/engine/cmd.go index 3707205e..e0ea5e3a 100644 --- a/pkg/engine/cmd.go +++ b/pkg/engine/cmd.go @@ -185,6 +185,8 @@ func appendInputAsEnv(env []string, input string) []string { dec := json.NewDecoder(bytes.NewReader([]byte(input))) dec.UseNumber() + env = appendEnv(env, "GPTSCRIPT_INPUT", input) + if err := json.Unmarshal([]byte(input), &data); err != nil { // ignore invalid JSON return env @@ -206,7 +208,6 @@ func appendInputAsEnv(env []string, input string) []string { } } - env = appendEnv(env, "GPTSCRIPT_INPUT", input) return env } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 2dd17b1f..9dd8c741 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -98,6 +98,7 @@ const ( ProviderToolCategory ToolCategory = "provider" CredentialToolCategory ToolCategory = "credential" ContextToolCategory ToolCategory = "context" + InputToolCategory ToolCategory = "input" NoCategory ToolCategory = "" ) @@ -180,7 +181,7 @@ func NewContext(ctx context.Context, prg *types.Program, input string) Context { return callCtx } -func (c *Context) SubCall(ctx context.Context, input, toolID, callID string, toolCategory ToolCategory) (Context, error) { +func (c *Context) SubCallContext(ctx context.Context, input, toolID, callID string, toolCategory ToolCategory) (Context, error) { tool, ok := c.Program.ToolSet[toolID] if !ok { return Context{}, fmt.Errorf("failed to file tool for id [%s]", toolID) diff --git a/pkg/openai/client.go b/pkg/openai/client.go index 8ed4014b..42ff83bc 100644 --- a/pkg/openai/client.go +++ b/pkg/openai/client.go @@ -2,7 +2,6 @@ package openai import ( "context" - "fmt" "io" "log/slog" "os" @@ -16,6 +15,7 @@ import ( "github.com/gptscript-ai/gptscript/pkg/counter" "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/hash" + "github.com/gptscript-ai/gptscript/pkg/mvl" "github.com/gptscript-ai/gptscript/pkg/prompt" "github.com/gptscript-ai/gptscript/pkg/system" "github.com/gptscript-ai/gptscript/pkg/types" @@ -29,6 +29,7 @@ const ( var ( key = os.Getenv("OPENAI_API_KEY") url = os.Getenv("OPENAI_BASE_URL") + log = mvl.Package() ) type InvalidAuthError struct{} @@ -305,7 +306,11 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques } if len(msgs) == 0 { - return nil, fmt.Errorf("invalid request, no messages to send to LLM") + log.Errorf("invalid request, no messages to send to LLM") + return &types.CompletionMessage{ + Role: types.CompletionMessageRoleTypeAssistant, + Content: types.Text(""), + }, nil } request := openai.ChatCompletionRequest{ diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index cf2f2cf9..e72dc32f 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -105,6 +105,10 @@ func isParam(line string, tool *types.Tool) (_ bool, err error) { tool.Parameters.Export = append(tool.Parameters.Export, csv(value)...) case "tool", "tools": tool.Parameters.Tools = append(tool.Parameters.Tools, csv(value)...) + case "inputfilter", "inputfilters": + tool.Parameters.InputFilters = append(tool.Parameters.InputFilters, csv(value)...) + case "shareinputfilter", "shareinputfilters": + tool.Parameters.ExportInputFilters = append(tool.Parameters.ExportInputFilters, csv(value)...) case "agent", "agents": tool.Parameters.Agents = append(tool.Parameters.Agents, csv(value)...) case "globaltool", "globaltools": @@ -183,10 +187,13 @@ type context struct { func (c *context) finish(tools *[]Node) { c.tool.Instructions = strings.TrimSpace(strings.Join(c.instructions, "")) - if c.tool.Instructions != "" || c.tool.Parameters.Name != "" || - len(c.tool.Export) > 0 || len(c.tool.Tools) > 0 || + if c.tool.Instructions != "" || + c.tool.Parameters.Name != "" || + len(c.tool.Export) > 0 || + len(c.tool.Tools) > 0 || c.tool.GlobalModelName != "" || len(c.tool.GlobalTools) > 0 || + len(c.tool.ExportInputFilters) > 0 || c.tool.Chat { *tools = append(*tools, Node{ ToolNode: &ToolNode{ diff --git a/pkg/parser/parser_test.go b/pkg/parser/parser_test.go index 9cdb593e..fb5a3ab7 100644 --- a/pkg/parser/parser_test.go +++ b/pkg/parser/parser_test.go @@ -191,3 +191,27 @@ name: bad }, }}).Equal(t, out) } + +func TestParseInput(t *testing.T) { + input := ` +input filters: input +share input filters: shared +` + out, err := Parse(strings.NewReader(input)) + require.NoError(t, err) + autogold.Expect(Document{Nodes: []Node{ + {ToolNode: &ToolNode{ + Tool: types.Tool{ + ToolDef: types.ToolDef{ + Parameters: types.Parameters{ + InputFilters: []string{ + "input", + }, + ExportInputFilters: []string{"shared"}, + }, + }, + Source: types.ToolSource{LineNo: 1}, + }, + }}, + }}).Equal(t, out) +} diff --git a/pkg/runner/input.go b/pkg/runner/input.go new file mode 100644 index 00000000..0d8cb7f0 --- /dev/null +++ b/pkg/runner/input.go @@ -0,0 +1,27 @@ +package runner + +import ( + "fmt" + + "github.com/gptscript-ai/gptscript/pkg/engine" +) + +func (r *Runner) handleInput(callCtx engine.Context, monitor Monitor, env []string, input string) (string, error) { + inputToolRefs, err := callCtx.Tool.GetInputFilterTools(*callCtx.Program) + if err != nil { + return "", err + } + + for _, inputToolRef := range inputToolRefs { + res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, inputToolRef.ToolID, input, "", engine.InputToolCategory) + if err != nil { + return "", err + } + if res.Result == nil { + return "", fmt.Errorf("invalid state: input tool [%s] can not result in a chat continuation", inputToolRef.Reference) + } + input = *res.Result + } + + return input, nil +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index fbb4622c..ddb4b102 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -408,6 +408,11 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en Content: input, }) + input, err := r.handleInput(callCtx, monitor, env, input) + if err != nil { + return nil, err + } + if len(callCtx.Tool.Credentials) > 0 { var err error env, err = r.handleCredentials(callCtx, monitor, env) @@ -417,7 +422,6 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en } var ( - err error newState *State ) callCtx.InputContext, newState, err = r.getContext(callCtx, state, monitor, env, input) @@ -446,7 +450,10 @@ func (r *Runner) start(callCtx engine.Context, state *State, monitor Monitor, en } if !authResp.Accept { - msg := fmt.Sprintf("[AUTHORIZATION ERROR]: %s", authResp.Message) + msg := authResp.Message + if msg == "" { + msg = "Tool call request has been denied" + } return &State{ Continuation: &engine.Return{ Result: &msg, @@ -631,8 +638,12 @@ func (r *Runner) resume(callCtx engine.Context, monitor Monitor, env []string, s } if state.ResumeInput != nil { + input, err := r.handleInput(callCtx, monitor, env, *state.ResumeInput) + if err != nil { + return state, err + } engineResults = append(engineResults, engine.CallResult{ - User: *state.ResumeInput, + User: input, }) } @@ -689,16 +700,22 @@ func streamProgress(callCtx *engine.Context, monitor Monitor) (chan<- types.Comp } func (r *Runner) subCall(ctx context.Context, parentContext engine.Context, monitor Monitor, env []string, toolID, input, callID string, toolCategory engine.ToolCategory) (*State, error) { - callCtx, err := parentContext.SubCall(ctx, input, toolID, callID, toolCategory) + callCtx, err := parentContext.SubCallContext(ctx, input, toolID, callID, toolCategory) if err != nil { return nil, err } + if toolCategory == engine.ContextToolCategory && callCtx.Tool.IsNoop() { + return &State{ + Result: new(string), + }, nil + } + return r.call(callCtx, monitor, env, input) } func (r *Runner) subCallResume(ctx context.Context, parentContext engine.Context, monitor Monitor, env []string, toolID, callID string, state *State, toolCategory engine.ToolCategory) (*State, error) { - callCtx, err := parentContext.SubCall(ctx, "", toolID, callID, toolCategory) + callCtx, err := parentContext.SubCallContext(ctx, "", toolID, callID, toolCategory) if err != nil { return nil, err } @@ -882,12 +899,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env input = string(inputBytes) } - subCtx, err := callCtx.SubCall(callCtx.Ctx, input, credToolRefs[0].ToolID, "", engine.CredentialToolCategory) // leaving callID as "" will cause it to be set by the engine - if err != nil { - return nil, fmt.Errorf("failed to create subcall context for tool %s: %w", credToolName, err) - } - - res, err := r.call(subCtx, monitor, env, input) + res, err := r.subCall(callCtx.Ctx, callCtx, monitor, env, credToolRefs[0].ToolID, input, "", engine.CredentialToolCategory) if err != nil { return nil, fmt.Errorf("failed to run credential tool %s: %w", credToolName, err) } diff --git a/pkg/tests/runner_test.go b/pkg/tests/runner_test.go index fb698a0e..4333f398 100644 --- a/pkg/tests/runner_test.go +++ b/pkg/tests/runner_test.go @@ -822,3 +822,24 @@ func TestAgents(t *testing.T) { autogold.Expect("TEST RESULT CALL: 4").Equal(t, resp.Content) autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step1")) } + +func TestInput(t *testing.T) { + r := tester.NewRunner(t) + + prg, err := r.Load("") + require.NoError(t, err) + + resp, err := r.Chat(context.Background(), nil, prg, nil, "You're stupid") + require.NoError(t, err) + r.AssertResponded(t) + assert.False(t, resp.Done) + autogold.Expect("TEST RESULT CALL: 1").Equal(t, resp.Content) + autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step1")) + + resp, err = r.Chat(context.Background(), resp.State, prg, nil, "You're ugly") + require.NoError(t, err) + r.AssertResponded(t) + assert.False(t, resp.Done) + autogold.Expect("TEST RESULT CALL: 2").Equal(t, resp.Content) + autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step2")) +} diff --git a/pkg/tests/testdata/TestInput/call1-resp.golden b/pkg/tests/testdata/TestInput/call1-resp.golden new file mode 100644 index 00000000..2861a036 --- /dev/null +++ b/pkg/tests/testdata/TestInput/call1-resp.golden @@ -0,0 +1,9 @@ +`{ + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 1" + } + ], + "usage": {} +}` diff --git a/pkg/tests/testdata/TestInput/call1.golden b/pkg/tests/testdata/TestInput/call1.golden new file mode 100644 index 00000000..8f9b629c --- /dev/null +++ b/pkg/tests/testdata/TestInput/call1.golden @@ -0,0 +1,24 @@ +`{ + "model": "gpt-4o", + "internalSystemPrompt": false, + "messages": [ + { + "role": "system", + "content": [ + { + "text": "\nTool body" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're stupid!\n ha ha ha\n" + } + ], + "usage": {} + } + ] +}` diff --git a/pkg/tests/testdata/TestInput/call2-resp.golden b/pkg/tests/testdata/TestInput/call2-resp.golden new file mode 100644 index 00000000..997ca1b9 --- /dev/null +++ b/pkg/tests/testdata/TestInput/call2-resp.golden @@ -0,0 +1,9 @@ +`{ + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 2" + } + ], + "usage": {} +}` diff --git a/pkg/tests/testdata/TestInput/call2.golden b/pkg/tests/testdata/TestInput/call2.golden new file mode 100644 index 00000000..8da96da8 --- /dev/null +++ b/pkg/tests/testdata/TestInput/call2.golden @@ -0,0 +1,42 @@ +`{ + "model": "gpt-4o", + "internalSystemPrompt": false, + "messages": [ + { + "role": "system", + "content": [ + { + "text": "\nTool body" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're stupid!\n ha ha ha\n" + } + ], + "usage": {} + }, + { + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 1" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're ugly!\n ha ha ha\n" + } + ], + "usage": {} + } + ] +}` diff --git a/pkg/tests/testdata/TestInput/step1.golden b/pkg/tests/testdata/TestInput/step1.golden new file mode 100644 index 00000000..a617d41a --- /dev/null +++ b/pkg/tests/testdata/TestInput/step1.golden @@ -0,0 +1,47 @@ +`{ + "done": false, + "content": "TEST RESULT CALL: 1", + "toolID": "testdata/TestInput/test.gpt:", + "state": { + "continuation": { + "state": { + "input": "No, You're stupid!\n ha ha ha\n", + "completion": { + "model": "gpt-4o", + "internalSystemPrompt": false, + "messages": [ + { + "role": "system", + "content": [ + { + "text": "\nTool body" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're stupid!\n ha ha ha\n" + } + ], + "usage": {} + }, + { + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 1" + } + ], + "usage": {} + } + ] + } + }, + "result": "TEST RESULT CALL: 1" + }, + "continuationToolID": "testdata/TestInput/test.gpt:" + } +}` diff --git a/pkg/tests/testdata/TestInput/step2.golden b/pkg/tests/testdata/TestInput/step2.golden new file mode 100644 index 00000000..e085edb2 --- /dev/null +++ b/pkg/tests/testdata/TestInput/step2.golden @@ -0,0 +1,65 @@ +`{ + "done": false, + "content": "TEST RESULT CALL: 2", + "toolID": "testdata/TestInput/test.gpt:", + "state": { + "continuation": { + "state": { + "input": "No, You're stupid!\n ha ha ha\n", + "completion": { + "model": "gpt-4o", + "internalSystemPrompt": false, + "messages": [ + { + "role": "system", + "content": [ + { + "text": "\nTool body" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're stupid!\n ha ha ha\n" + } + ], + "usage": {} + }, + { + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 1" + } + ], + "usage": {} + }, + { + "role": "user", + "content": [ + { + "text": "No, You're ugly!\n ha ha ha\n" + } + ], + "usage": {} + }, + { + "role": "assistant", + "content": [ + { + "text": "TEST RESULT CALL: 2" + } + ], + "usage": {} + } + ] + } + }, + "result": "TEST RESULT CALL: 2" + }, + "continuationToolID": "testdata/TestInput/test.gpt:" + } +}` diff --git a/pkg/tests/testdata/TestInput/test.gpt b/pkg/tests/testdata/TestInput/test.gpt new file mode 100644 index 00000000..bcb85a43 --- /dev/null +++ b/pkg/tests/testdata/TestInput/test.gpt @@ -0,0 +1,23 @@ +input filter: taunt +context: exporter +chat: true + +Tool body + +--- +name: taunt +args: foo: this is useless +#!/bin/bash + +echo "No, ${GPTSCRIPT_INPUT}!" + +--- +name: exporter +share input filters: taunt2 + +--- +name: taunt2 +args: foo: this is useless + +#!/bin/bash +echo "${GPTSCRIPT_INPUT} ha ha ha" \ No newline at end of file diff --git a/pkg/types/set.go b/pkg/types/set.go index 9ff6b22e..230e112b 100644 --- a/pkg/types/set.go +++ b/pkg/types/set.go @@ -29,7 +29,7 @@ func (t *toolRefSet) HasTool(toolID string) bool { } func (t *toolRefSet) AddAll(values []ToolReference, err error) { - if t.err != nil { + if err != nil { t.err = err } for _, v := range values { diff --git a/pkg/types/tool.go b/pkg/types/tool.go index 9468a04a..cc84264d 100644 --- a/pkg/types/tool.go +++ b/pkg/types/tool.go @@ -120,26 +120,28 @@ func (p Program) SetBlocking() Program { type BuiltinFunc func(ctx context.Context, env []string, input string, progress chan<- string) (string, error) type Parameters struct { - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - MaxTokens int `json:"maxTokens,omitempty"` - ModelName string `json:"modelName,omitempty"` - ModelProvider bool `json:"modelProvider,omitempty"` - JSONResponse bool `json:"jsonResponse,omitempty"` - Chat bool `json:"chat,omitempty"` - Temperature *float32 `json:"temperature,omitempty"` - Cache *bool `json:"cache,omitempty"` - InternalPrompt *bool `json:"internalPrompt"` - Arguments *openapi3.Schema `json:"arguments,omitempty"` - Tools []string `json:"tools,omitempty"` - GlobalTools []string `json:"globalTools,omitempty"` - GlobalModelName string `json:"globalModelName,omitempty"` - Context []string `json:"context,omitempty"` - ExportContext []string `json:"exportContext,omitempty"` - Export []string `json:"export,omitempty"` - Agents []string `json:"agents,omitempty"` - Credentials []string `json:"credentials,omitempty"` - Blocking bool `json:"-"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + MaxTokens int `json:"maxTokens,omitempty"` + ModelName string `json:"modelName,omitempty"` + ModelProvider bool `json:"modelProvider,omitempty"` + JSONResponse bool `json:"jsonResponse,omitempty"` + Chat bool `json:"chat,omitempty"` + Temperature *float32 `json:"temperature,omitempty"` + Cache *bool `json:"cache,omitempty"` + InternalPrompt *bool `json:"internalPrompt"` + Arguments *openapi3.Schema `json:"arguments,omitempty"` + Tools []string `json:"tools,omitempty"` + GlobalTools []string `json:"globalTools,omitempty"` + GlobalModelName string `json:"globalModelName,omitempty"` + Context []string `json:"context,omitempty"` + ExportContext []string `json:"exportContext,omitempty"` + Export []string `json:"export,omitempty"` + Agents []string `json:"agents,omitempty"` + Credentials []string `json:"credentials,omitempty"` + InputFilters []string `json:"inputFilters,omitempty"` + ExportInputFilters []string `json:"exportInputFilters,omitempty"` + Blocking bool `json:"-"` } func (p Parameters) ToolRefNames() []string { @@ -149,7 +151,9 @@ func (p Parameters) ToolRefNames() []string { p.Export, p.ExportContext, p.Context, - p.Credentials) + p.Credentials, + p.InputFilters, + p.ExportInputFilters) } type ToolDef struct { @@ -379,11 +383,17 @@ func (t ToolDef) String() string { if len(t.Parameters.Export) != 0 { _, _ = fmt.Fprintf(buf, "Share Tools: %s\n", strings.Join(t.Parameters.Export, ", ")) } + if len(t.Parameters.Context) != 0 { + _, _ = fmt.Fprintf(buf, "Context: %s\n", strings.Join(t.Parameters.Context, ", ")) + } if len(t.Parameters.ExportContext) != 0 { _, _ = fmt.Fprintf(buf, "Share Context: %s\n", strings.Join(t.Parameters.ExportContext, ", ")) } - if len(t.Parameters.Context) != 0 { - _, _ = fmt.Fprintf(buf, "Context: %s\n", strings.Join(t.Parameters.Context, ", ")) + if len(t.Parameters.InputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Input Filters: %s\n", strings.Join(t.Parameters.InputFilters, ", ")) + } + if len(t.Parameters.ExportInputFilters) != 0 { + _, _ = fmt.Fprintf(buf, "Share Input Filters: %s\n", strings.Join(t.Parameters.ExportInputFilters, ", ")) } if t.Parameters.MaxTokens != 0 { _, _ = fmt.Fprintf(buf, "Max Tokens: %d\n", t.Parameters.MaxTokens) @@ -469,6 +479,8 @@ func (t Tool) GetExportedTools(prg Program) ([]ToolReference, error) { return result.List() } +// GetContextTools returns all tools that are in the context of the tool including all the +// contexts that are exported by the context tools. This will recurse all exports. func (t Tool) GetContextTools(prg Program) ([]ToolReference, error) { result := &toolRefSet{} @@ -485,6 +497,31 @@ func (t Tool) GetContextTools(prg Program) ([]ToolReference, error) { return result.List() } +func (t Tool) GetInputFilterTools(program Program) ([]ToolReference, error) { + result := &toolRefSet{} + + inputFilterRefs, err := t.GetToolRefsFromNames(t.InputFilters) + if err != nil { + return nil, err + } + + for _, inputFilterRef := range inputFilterRefs { + result.Add(inputFilterRef) + } + + contextRefs, err := t.GetContextTools(program) + if err != nil { + return nil, err + } + + for _, contextRef := range contextRefs { + contextTool := program.ToolSet[contextRef.ToolID] + result.AddAll(contextTool.GetToolRefsFromNames(contextTool.ExportInputFilters)) + } + + return result.List() +} + func (t Tool) GetAgentGroup(agentGroup []ToolReference, toolID string) (result []ToolReference, _ error) { newAgentGroup := toolRefSet{} if err := t.addAgents(&newAgentGroup); err != nil { @@ -659,6 +696,10 @@ func (t Tool) GetInterpreter() string { return fields[0] } +func (t Tool) IsNoop() bool { + return t.Instructions == "" +} + func (t Tool) IsCommand() bool { return strings.HasPrefix(t.Instructions, CommandPrefix) } diff --git a/pkg/types/tool_test.go b/pkg/types/tool_test.go index f1edc340..6e3d98d3 100644 --- a/pkg/types/tool_test.go +++ b/pkg/types/tool_test.go @@ -9,26 +9,28 @@ import ( func TestToolDef_String(t *testing.T) { tool := ToolDef{ Parameters: Parameters{ - Name: "Tool Sample", - Description: "This is a sample tool", - MaxTokens: 1024, - ModelName: "ModelSample", - ModelProvider: true, - JSONResponse: true, - Chat: true, - Temperature: float32Ptr(0.8), - Cache: boolPtr(true), - InternalPrompt: boolPtr(true), - Arguments: ObjectSchema("arg1", "desc1", "arg2", "desc2"), - Tools: []string{"Tool1", "Tool2"}, - GlobalTools: []string{"GlobalTool1", "GlobalTool2"}, - GlobalModelName: "GlobalModelSample", - Context: []string{"Context1", "Context2"}, - ExportContext: []string{"ExportContext1", "ExportContext2"}, - Export: []string{"Export1", "Export2"}, - Agents: []string{"Agent1", "Agent2"}, - Credentials: []string{"Credential1", "Credential2"}, - Blocking: true, + Name: "Tool Sample", + Description: "This is a sample tool", + MaxTokens: 1024, + ModelName: "ModelSample", + ModelProvider: true, + JSONResponse: true, + Chat: true, + Temperature: float32Ptr(0.8), + Cache: boolPtr(true), + InternalPrompt: boolPtr(true), + Arguments: ObjectSchema("arg1", "desc1", "arg2", "desc2"), + Tools: []string{"Tool1", "Tool2"}, + GlobalTools: []string{"GlobalTool1", "GlobalTool2"}, + GlobalModelName: "GlobalModelSample", + Context: []string{"Context1", "Context2"}, + ExportContext: []string{"ExportContext1", "ExportContext2"}, + Export: []string{"Export1", "Export2"}, + Agents: []string{"Agent1", "Agent2"}, + Credentials: []string{"Credential1", "Credential2"}, + Blocking: true, + InputFilters: []string{"Filter1", "Filter2"}, + ExportInputFilters: []string{"SharedFilter1", "SharedFilter2"}, }, Instructions: "This is a sample instruction", } @@ -40,8 +42,10 @@ Description: This is a sample tool Agents: Agent1, Agent2 Tools: Tool1, Tool2 Share Tools: Export1, Export2 -Share Context: ExportContext1, ExportContext2 Context: Context1, Context2 +Share Context: ExportContext1, ExportContext2 +Input Filters: Filter1, Filter2 +Share Input Filters: SharedFilter1, SharedFilter2 Max Tokens: 1024 Model: ModelSample Model Provider: true