diff --git a/pkg/tools/builtin/script_shell.go b/pkg/tools/builtin/script_shell.go index 4753cd717..6c45fdf6d 100644 --- a/pkg/tools/builtin/script_shell.go +++ b/pkg/tools/builtin/script_shell.go @@ -144,7 +144,7 @@ func (t *ScriptShellTool) execute(ctx context.Context, toolConfig *latest.Script cmd.Env = t.env for key, value := range params { if value != nil { - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, value)) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%v", key, value)) } } diff --git a/pkg/tools/builtin/script_shell_test.go b/pkg/tools/builtin/script_shell_test.go index 7388b1ea9..dbb36eb9b 100644 --- a/pkg/tools/builtin/script_shell_test.go +++ b/pkg/tools/builtin/script_shell_test.go @@ -2,12 +2,14 @@ package builtin import ( "encoding/json" + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/docker/docker-agent/pkg/config/latest" + "github.com/docker/docker-agent/pkg/tools" ) func TestNewScriptShellTool_Empty(t *testing.T) { @@ -116,6 +118,43 @@ func TestNewScriptShellTool_MissingRequired(t *testing.T) { require.ErrorContains(t, err, "tool 'docker_images' has required arg 'img' which is not defined in args") } +func TestNewScriptShellTool_NumberArg(t *testing.T) { + shellTools := map[string]latest.ScriptShellToolConfig{ + "repeat": { + Description: "Repeat a message N times", + Cmd: "for i in $(seq 1 $count); do echo $message; done", + Args: map[string]any{ + "message": map[string]any{ + "description": "Message to repeat", + "type": "string", + }, + "count": map[string]any{ + "description": "Number of repetitions", + "type": "number", + }, + }, + Required: []string{"message", "count"}, + }, + } + + tool, err := NewScriptShellTool(shellTools, os.Environ()) + require.NoError(t, err) + + allTools, err := tool.Tools(t.Context()) + require.NoError(t, err) + require.Len(t, allTools, 1) + + // Simulate LLM sending a number argument (JSON numbers are float64) + result, err := allTools[0].Handler(t.Context(), tools.ToolCall{ + Function: tools.FunctionCall{ + Arguments: `{"message": "hello", "count": 3}`, + }, + }) + require.NoError(t, err) + assert.False(t, result.IsError, "unexpected error: %s", result.Output) + assert.Equal(t, "hello\nhello\nhello\n", result.Output) +} + func TestNewScriptShellTool_ArgWithoutType(t *testing.T) { shellTools := map[string]latest.ScriptShellToolConfig{ "greet": {