Skip to content

Commit 452354d

Browse files
committed
feat: pass forward downstream app flags
1 parent 8c1533a commit 452354d

2 files changed

Lines changed: 26 additions & 13 deletions

File tree

cmd/cli/commands/launch.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ func newLaunchCmd() *cobra.Command {
7676
dryRun bool
7777
)
7878
c := &cobra.Command{
79-
Use: "launch APP",
79+
Use: "launch APP [-- APP_ARGS...]",
8080
Short: "Launch an app configured to use Docker Model Runner",
81-
Args: requireExactArgs(1, "launch", "APP"),
81+
Args: cobra.MinimumNArgs(1),
8282
ValidArgs: supportedApps,
8383
RunE: func(cmd *cobra.Command, args []string) error {
8484
app := strings.ToLower(args[0])
85+
appArgs := args[1:]
8586

8687
runner, err := getStandaloneRunner(cmd.Context())
8788
if err != nil {
@@ -97,7 +98,7 @@ func newLaunchCmd() *cobra.Command {
9798
return launchContainerApp(cmd, ca, ep.container, image, port, detach, dryRun)
9899
}
99100
if cli, ok := hostApps[app]; ok {
100-
return launchHostApp(cmd, app, ep.host, cli, dryRun)
101+
return launchHostApp(cmd, app, ep.host, cli, appArgs, dryRun)
101102
}
102103
return fmt.Errorf("unsupported app %q (supported: %s)", app, strings.Join(supportedApps, ", "))
103104
},
@@ -180,7 +181,7 @@ func launchContainerApp(cmd *cobra.Command, ca containerApp, baseURL string, ima
180181
}
181182

182183
// launchHostApp launches a native host app executable.
183-
func launchHostApp(cmd *cobra.Command, bin string, baseURL string, cli hostApp, dryRun bool) error {
184+
func launchHostApp(cmd *cobra.Command, bin string, baseURL string, cli hostApp, appArgs []string, dryRun bool) error {
184185
if _, err := exec.LookPath(bin); err != nil {
185186
cmd.Printf("%q executable not found in PATH.\n", bin)
186187
if cli.envFn != nil {
@@ -198,13 +199,13 @@ func launchHostApp(cmd *cobra.Command, bin string, baseURL string, cli hostApp,
198199

199200
env := cli.envFn(baseURL)
200201
if dryRun {
201-
cmd.Printf("Would run: %s\n", bin)
202+
cmd.Printf("Would run: %s %s\n", bin, strings.Join(appArgs, " "))
202203
for _, e := range env {
203204
cmd.Printf(" %s\n", e)
204205
}
205206
return nil
206207
}
207-
return runExternal(cmd, withEnv(env...), bin)
208+
return runExternal(cmd, withEnv(env...), bin, appArgs...)
208209
}
209210

210211
// launchUnconfigurableHostApp handles host apps that need manual config rather than env vars.

cmd/cli/commands/launch_test.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ func TestLaunchHostAppDryRunOpenai(t *testing.T) {
230230

231231
cli := hostApp{envFn: openaiEnv(openaiPathSuffix)}
232232
// Use "ls" as a bin that exists in PATH
233-
err := launchHostApp(cmd, "ls", testBaseURL, cli, true)
233+
err := launchHostApp(cmd, "ls", testBaseURL, cli, nil, true)
234234
require.NoError(t, err)
235235

236236
output := buf.String()
@@ -245,7 +245,7 @@ func TestLaunchHostAppDryRunCodex(t *testing.T) {
245245
cmd := newTestCmd(buf)
246246

247247
cli := hostApp{envFn: openaiEnv("/v1")}
248-
err := launchHostApp(cmd, "ls", testBaseURL, cli, true)
248+
err := launchHostApp(cmd, "ls", testBaseURL, cli, nil, true)
249249
require.NoError(t, err)
250250

251251
output := buf.String()
@@ -255,12 +255,24 @@ func TestLaunchHostAppDryRunCodex(t *testing.T) {
255255
require.NotContains(t, output, "/engines/v1")
256256
}
257257

258+
func TestLaunchHostAppDryRunWithArgs(t *testing.T) {
259+
buf := new(bytes.Buffer)
260+
cmd := newTestCmd(buf)
261+
262+
cli := hostApp{envFn: openaiEnv(openaiPathSuffix)}
263+
err := launchHostApp(cmd, "ls", testBaseURL, cli, []string{"-m", "ai/qwen3"}, true)
264+
require.NoError(t, err)
265+
266+
output := buf.String()
267+
require.Contains(t, output, "Would run: ls -m ai/qwen3")
268+
}
269+
258270
func TestLaunchHostAppDryRunAnthropic(t *testing.T) {
259271
buf := new(bytes.Buffer)
260272
cmd := newTestCmd(buf)
261273

262274
cli := hostApp{envFn: anthropicEnv}
263-
err := launchHostApp(cmd, "ls", testBaseURL, cli, true)
275+
err := launchHostApp(cmd, "ls", testBaseURL, cli, nil, true)
264276
require.NoError(t, err)
265277

266278
output := buf.String()
@@ -275,7 +287,7 @@ func TestLaunchHostAppNotFound(t *testing.T) {
275287
cmd := newTestCmd(buf)
276288

277289
cli := hostApp{envFn: openaiEnv(openaiPathSuffix)}
278-
err := launchHostApp(cmd, "nonexistent-binary-xyz", testBaseURL, cli, false)
290+
err := launchHostApp(cmd, "nonexistent-binary-xyz", testBaseURL, cli, nil, false)
279291
require.Error(t, err)
280292
require.Contains(t, err.Error(), "not found")
281293

@@ -289,7 +301,7 @@ func TestLaunchHostAppNotFoundNilEnvFn(t *testing.T) {
289301
cmd := newTestCmd(buf)
290302

291303
cli := hostApp{envFn: nil}
292-
err := launchHostApp(cmd, "nonexistent-binary-xyz", testBaseURL, cli, false)
304+
err := launchHostApp(cmd, "nonexistent-binary-xyz", testBaseURL, cli, nil, false)
293305
require.Error(t, err)
294306

295307
output := buf.String()
@@ -326,13 +338,13 @@ func TestNewLaunchCmdValidArgs(t *testing.T) {
326338
require.Equal(t, supportedApps, cmd.ValidArgs)
327339
}
328340

329-
func TestNewLaunchCmdRequiresExactlyOneArg(t *testing.T) {
341+
func TestNewLaunchCmdRequiresAtLeastOneArg(t *testing.T) {
330342
cmd := newLaunchCmd()
331343
cmd.SetArgs([]string{})
332344
err := cmd.Execute()
333345

334346
require.Error(t, err)
335-
require.Contains(t, err.Error(), "requires 1 argument")
347+
require.Contains(t, err.Error(), "requires at least 1 arg")
336348
}
337349

338350
func TestNewLaunchCmdDispatchContainerApp(t *testing.T) {

0 commit comments

Comments
 (0)