From a5df8333e944fdd2917d30506c551c2f0223bea9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:52:01 +0000 Subject: [PATCH 1/3] Initial plan From d110242dadb4800842683b50ee20e41d5acfefd3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:58:23 +0000 Subject: [PATCH 2/3] Fix module import by using shellwords.Parse directly Co-authored-by: ericcurtin <1694275+ericcurtin@users.noreply.github.com> --- main.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 317270ddc..75e44db36 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,7 @@ import ( "github.com/docker/model-runner/pkg/inference/scheduling" "github.com/docker/model-runner/pkg/metrics" "github.com/docker/model-runner/pkg/routing" - "github.com/docker/model-runner/pkg/utils" + "github.com/mattn/go-shellwords" "github.com/sirupsen/logrus" ) @@ -255,7 +255,10 @@ func createLlamaCppConfigFromEnv() config.BackendConfig { } // Split the string by spaces, respecting quoted arguments - args := utils.SplitArgs(argsStr) + args, err := shellwords.Parse(argsStr) + if err != nil { + log.Fatalf("Failed to parse LLAMA_ARGS: %v", err) + } // Check for disallowed arguments disallowedArgs := []string{"--model", "--host", "--embeddings", "--mmproj"} From adb4e86bbd230dc934c745a60964afe2c51116d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:29:24 +0000 Subject: [PATCH 3/3] Create pkg/utils package with SplitArgs function Co-authored-by: ericcurtin <1694275+ericcurtin@users.noreply.github.com> --- main.go | 7 ++--- pkg/utils/args.go | 17 ++++++++++++ pkg/utils/args_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 pkg/utils/args.go create mode 100644 pkg/utils/args_test.go diff --git a/main.go b/main.go index 75e44db36..317270ddc 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,7 @@ import ( "github.com/docker/model-runner/pkg/inference/scheduling" "github.com/docker/model-runner/pkg/metrics" "github.com/docker/model-runner/pkg/routing" - "github.com/mattn/go-shellwords" + "github.com/docker/model-runner/pkg/utils" "github.com/sirupsen/logrus" ) @@ -255,10 +255,7 @@ func createLlamaCppConfigFromEnv() config.BackendConfig { } // Split the string by spaces, respecting quoted arguments - args, err := shellwords.Parse(argsStr) - if err != nil { - log.Fatalf("Failed to parse LLAMA_ARGS: %v", err) - } + args := utils.SplitArgs(argsStr) // Check for disallowed arguments disallowedArgs := []string{"--model", "--host", "--embeddings", "--mmproj"} diff --git a/pkg/utils/args.go b/pkg/utils/args.go new file mode 100644 index 000000000..6d9cceb85 --- /dev/null +++ b/pkg/utils/args.go @@ -0,0 +1,17 @@ +package utils + +import ( + "github.com/mattn/go-shellwords" +) + +// SplitArgs splits a string into arguments, respecting quoted strings. +// This is a wrapper around shellwords.Parse for convenience. +func SplitArgs(s string) []string { + args, err := shellwords.Parse(s) + if err != nil { + // If parsing fails, return empty slice + // The caller can check for empty result + return []string{} + } + return args +} diff --git a/pkg/utils/args_test.go b/pkg/utils/args_test.go new file mode 100644 index 000000000..18192a884 --- /dev/null +++ b/pkg/utils/args_test.go @@ -0,0 +1,59 @@ +package utils + +import ( + "reflect" + "testing" +) + +func TestSplitArgs(t *testing.T) { + tests := []struct { + name string + input string + expected []string + }{ + { + name: "simple arguments", + input: "arg1 arg2 arg3", + expected: []string{"arg1", "arg2", "arg3"}, + }, + { + name: "quoted arguments", + input: `arg1 "arg with spaces" arg3`, + expected: []string{"arg1", "arg with spaces", "arg3"}, + }, + { + name: "single quoted arguments", + input: `arg1 'arg with spaces' arg3`, + expected: []string{"arg1", "arg with spaces", "arg3"}, + }, + { + name: "mixed quotes", + input: `arg1 "double quoted" 'single quoted' arg4`, + expected: []string{"arg1", "double quoted", "single quoted", "arg4"}, + }, + { + name: "empty string", + input: "", + expected: []string{}, + }, + { + name: "flags with values", + input: "--flag1 value1 --flag2 value2", + expected: []string{"--flag1", "value1", "--flag2", "value2"}, + }, + { + name: "flags with quoted values", + input: `--flag1 "value with spaces" --flag2 value2`, + expected: []string{"--flag1", "value with spaces", "--flag2", "value2"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := SplitArgs(tt.input) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("SplitArgs(%q) = %v, expected %v", tt.input, result, tt.expected) + } + }) + } +}