Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions cmd/cli/commands/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package commands

import "github.com/spf13/cobra"

func newConfigCmd() *cobra.Command {
c := &cobra.Command{
Use: "config",
Short: "Manage persistent model runner configuration",
}

c.AddCommand(newSandboxConfigCmd())

return c
}
7 changes: 3 additions & 4 deletions cmd/cli/commands/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ func newConfigureCmd() *cobra.Command {
var flags ConfigureFlags

c := &cobra.Command{
Use: "configure [--context-size=<n>] [--speculative-draft-model=<model>] [--hf_overrides=<json>] [--gpu-memory-utilization=<float>] [--mode=<mode>] [--think] [--keep-alive=<duration>] MODEL [-- <runtime-flags...>]",
Aliases: []string{"config"},
Short: "Manage model runtime configurations",
Hidden: true,
Use: "configure [--context-size=<n>] [--speculative-draft-model=<model>] [--hf_overrides=<json>] [--gpu-memory-utilization=<float>] [--mode=<mode>] [--think] [--keep-alive=<duration>] MODEL [-- <runtime-flags...>]",
Short: "Manage model runtime configurations",
Comment thread
CoderHariswar marked this conversation as resolved.
Hidden: true,
Args: func(cmd *cobra.Command, args []string) error {
argsBeforeDash := cmd.ArgsLenAtDash()
if argsBeforeDash == -1 {
Expand Down
26 changes: 21 additions & 5 deletions cmd/cli/commands/launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ Examples:
appArgs = args[dashIdx:]
}

// If a sandbox tool is configured, launch host apps through it before
// resolving runner endpoints. This keeps sandbox launch independent of
// whether the host app binary itself is installed.
if _, ok := hostApps[app]; ok {
sandboxTool, err := configuredSandboxTool()
if err != nil {
return err
}

if sandboxTool != "" {
return launchSandboxedHostApp(cmd, sandboxTool, app, appArgs, dryRun)
}
}

runner, err := getStandaloneRunner(cmd.Context())
if err != nil {
return fmt.Errorf("unable to determine standalone runner endpoint: %w", err)
Expand All @@ -146,18 +160,17 @@ Examples:
if err != nil {
return err
}

// --config: print configuration without launching
if configOnly {
return printAppConfig(cmd, app, ep, image, port)
}

if ca, ok := containerApps[app]; ok {
return launchContainerApp(cmd, ca, ep.container, image, port, detach, appArgs, dryRun)
}
if cli, ok := hostApps[app]; ok {
return launchHostApp(cmd, app, ep.host, cli, model, runner, appArgs, dryRun)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extra change

return fmt.Errorf("unsupported app %q (supported: %s)", app, strings.Join(supportedApps, ", "))
},
}
Expand All @@ -170,6 +183,12 @@ Examples:
return c
}

func launchSandboxedHostApp(cmd *cobra.Command, sandboxTool, app string, appArgs []string, dryRun bool) error {
args := append([]string{app}, appArgs...)

return runSandboxTool(cmd, sandboxTool, args, dryRun)
}

// listSupportedApps prints all supported apps with their descriptions and install status.
func listSupportedApps(cmd *cobra.Command) error {
cmd.Println("Supported apps:")
Expand Down Expand Up @@ -322,7 +341,6 @@ func launchHostApp(cmd *cobra.Command, bin string, baseURL string, cli hostApp,
if bin == "opencode" {
return launchOpenCode(cmd, baseURL, model, runner, appArgs, dryRun)
}

if !dryRun {
if _, err := exec.LookPath(bin); err != nil {
cmd.PrintErrf("%q executable not found in PATH.\n", bin)
Expand All @@ -335,11 +353,9 @@ func launchHostApp(cmd *cobra.Command, bin string, baseURL string, cli hostApp,
return fmt.Errorf("%s not found; please install it and re-run", bin)
}
}

if cli.envFn == nil {
return launchUnconfigurableHostApp(cmd, bin, baseURL, cli, appArgs, dryRun)
}

env := cli.envFn(baseURL)
if dryRun {
cmd.Printf("Would run: %s %s\n", bin, strings.Join(appArgs, " "))
Expand Down
1 change: 1 addition & 0 deletions cmd/cli/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func NewRootCmd(cli *command.DockerCli) *cobra.Command {
newShowCmd(),
newComposeCmd(),
newLaunchCmd(),
newConfigCmd(),
newTagCmd(),
newConfigureCmd(),
newPSCmd(),
Expand Down
156 changes: 156 additions & 0 deletions cmd/cli/commands/sandbox.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package commands

import (
"bufio"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/spf13/cobra"
)

var allowedSandboxTools = map[string]struct{}{
"sbx": {},
}

func newSandboxConfigCmd() *cobra.Command {
return &cobra.Command{
Use: "sandbox.tool <tool>",
Short: "Set the sandbox tool",
Args: cobra.ExactArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
tool, err := validateSandboxTool(args[0])
if err != nil {
return err
}

return writeSandboxToolConfig(tool)
},
}
}

func validateSandboxTool(tool string) (string, error) {
if _, ok := allowedSandboxTools[tool]; !ok {
return "", fmt.Errorf("unsupported sandbox tool %q", tool)
}

return tool, nil
}

func dmrConfigPath() (string, error) {
configDir, err := os.UserConfigDir()
if err != nil {
return "", fmt.Errorf("unable to determine config directory: %w", err)
}

return filepath.Join(configDir, "dmr", "config.toml"), nil
}

func writeSandboxToolConfig(tool string) error {
path, err := dmrConfigPath()
if err != nil {
return err
}

if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return fmt.Errorf("unable to create config directory: %w", err)
}

content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool)

if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
return fmt.Errorf("unable to write config: %w", err)
}

return nil
}

func readSandboxToolConfig() (string, error) {
path, err := dmrConfigPath()
if err != nil {
return "", err
}

file, err := os.Open(path)
if os.IsNotExist(err) {
return "", nil
}
if err != nil {
return "", fmt.Errorf("unable to read config: %w", err)
}
defer file.Close()

inSandboxSection := false
scanner := bufio.NewScanner(file)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())

if line == "" || strings.HasPrefix(line, "#") {
continue
}

if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
inSandboxSection = line == "[sandbox]"
continue
}

if !inSandboxSection {
continue
}

key, value, ok := strings.Cut(line, "=")
if !ok {
continue
}

if strings.TrimSpace(key) != "tool" {
continue
}

return strings.Trim(strings.TrimSpace(value), `"`), nil
}

if err := scanner.Err(); err != nil {
return "", fmt.Errorf("unable to parse config: %w", err)
}

return "", nil
}
func runSandboxTool(cmd *cobra.Command, sandboxTool string, args []string, dryRun bool) error {
validatedSandboxTool, err := validateSandboxTool(sandboxTool)
if err != nil {
return err
}

if dryRun {
cmd.Printf("%s %s\n", validatedSandboxTool, strings.Join(args, " "))
return nil
}

switch validatedSandboxTool {
case "sbx":
launchCmd := exec.Command("sbx", args...)
launchCmd.Stdin = os.Stdin
launchCmd.Stdout = os.Stdout
launchCmd.Stderr = os.Stderr

return launchCmd.Run()
default:
return fmt.Errorf("unsupported sandbox tool %q", validatedSandboxTool)
}
}
func configuredSandboxTool() (string, error) {
sandboxTool, err := readSandboxToolConfig()
if err != nil {
return "", err
}

if sandboxTool == "" {
return "", nil
}

return validateSandboxTool(sandboxTool)
}
Loading