From 5987585b2dd119e74581a9198c17f495db9d0408 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Thu, 3 Apr 2025 00:11:53 +0200 Subject: [PATCH] feat(llm): add default model/provider to auto configure the driver (#7) --- mcontainer/cli.py | 6 +++++ mcontainer/container.py | 22 +++++++++++++++---- mcontainer/drivers/goose/mc-init.sh | 12 +++++----- .../drivers/goose/update-goose-config.py | 20 +++++++++++++++++ mcontainer/models.py | 12 +++++----- mcontainer/user_config.py | 2 ++ 6 files changed, 59 insertions(+), 15 deletions(-) diff --git a/mcontainer/cli.py b/mcontainer/cli.py index 49927a0..d6c4136 100644 --- a/mcontainer/cli.py +++ b/mcontainer/cli.py @@ -163,6 +163,10 @@ def create_session( gid: Optional[int] = typer.Option( None, "--gid", help="Group ID to run the container as (defaults to host user)" ), + model: Optional[str] = typer.Option(None, "--model", "-m", help="Model to use"), + provider: Optional[str] = typer.Option( + None, "--provider", "-p", help="Provider to use" + ), ssh: bool = typer.Option(False, "--ssh", help="Start SSH server in the container"), ) -> None: """Create a new MC session @@ -269,6 +273,8 @@ def create_session( uid=target_uid, gid=target_gid, ssh=ssh, + model=model, + provider=provider, ) if session: diff --git a/mcontainer/container.py b/mcontainer/container.py index f6e7a79..bc38002 100644 --- a/mcontainer/container.py +++ b/mcontainer/container.py @@ -113,6 +113,8 @@ class ContainerManager: container_id=container_id, created_at=container.attrs["Created"], project=labels.get("mc.project"), + model=labels.get("mc.model"), + provider=labels.get("mc.provider"), ) # Get port mappings @@ -148,6 +150,8 @@ class ContainerManager: run_command: Optional[str] = None, uid: Optional[int] = None, gid: Optional[int] = None, + model: Optional[str] = None, + provider: Optional[str] = None, ssh: bool = False, ) -> Optional[Session]: """Create a new MC session @@ -456,8 +460,8 @@ class ContainerManager: # Determine container command and entrypoint container_command = None - entrypoint = None # Keep this initially None to mean "use Dockerfile default unless overridden" - target_shell = "/bin/bash" # Default final shell + entrypoint = None + target_shell = "/bin/bash" if run_command: # Set environment variable for mc-init.sh to pick up @@ -477,6 +481,14 @@ class ContainerManager: "Using default container entrypoint/command for interactive shell." ) + # Set default model/provider from user config if not explicitly provided + env_vars["MC_MODEL"] = model or self.user_config_manager.get( + "defaults.model", "" + ) + env_vars["MC_PROVIDER"] = provider or self.user_config_manager.get( + "defaults.provider", "" + ) + # Create container container = self.client.containers.create( image=driver.image, @@ -605,10 +617,12 @@ class ContainerManager: created_at=container.attrs["Created"], ports=ports, mcps=mcp_names, - run_command=run_command, # Store the command + run_command=run_command, uid=uid, gid=gid, - ssh=ssh, # Store SSH setting + model=model, + provider=provider, + ssh=ssh, ) # Save session to the session manager diff --git a/mcontainer/drivers/goose/mc-init.sh b/mcontainer/drivers/goose/mc-init.sh index aeb3295..813e584 100755 --- a/mcontainer/drivers/goose/mc-init.sh +++ b/mcontainer/drivers/goose/mc-init.sh @@ -49,7 +49,7 @@ if [ -d /root/.local/bin ]; then echo "Copying /root/.local/bin to /home/mcuser/.local/bin..." mkdir -p /home/mcuser/.local/bin cp -r /root/.local/bin/* /home/mcuser/.local/bin/ - chown -R $MC_USER_ID:$MC_GROUP_ID /home/mcuser/.local/bin + chown -R $MC_USER_ID:$MC_GROUP_ID /home/mcuser/.local fi # Start SSH server only if explicitly enabled @@ -158,16 +158,16 @@ else echo "Warning: update-goose-config.py script not found. Goose configuration will not be updated." fi -# Mark initialization as complete -echo "=== MC Initialization completed at $(date) ===" -echo "INIT_COMPLETE=true" > /init.status - # Run the user command first, if set, as mcuser if [ -n "$MC_RUN_COMMAND" ]; then - echo '--- Executing initial command: $MC_RUN_COMMAND ---'; + echo "--- Executing initial command: $MC_RUN_COMMAND ---"; gosu mcuser sh -c "$MC_RUN_COMMAND"; # Run user command as mcuser COMMAND_EXIT_CODE=$?; echo "--- Initial command finished (exit code: $COMMAND_EXIT_CODE) ---"; fi; +# Mark initialization as complete +echo "=== MC Initialization completed at $(date) ===" +echo "INIT_COMPLETE=true" > /init.status + exec gosu mcuser "$@" diff --git a/mcontainer/drivers/goose/update-goose-config.py b/mcontainer/drivers/goose/update-goose-config.py index 26375c6..7395fc2 100644 --- a/mcontainer/drivers/goose/update-goose-config.py +++ b/mcontainer/drivers/goose/update-goose-config.py @@ -30,6 +30,26 @@ def update_config(): if "extensions" not in config_data: config_data["extensions"] = {} + # Add default developer extension + config_data["extensions"]["developer"] = { + "enabled": True, + "name": "developer", + "timeout": 300, + "type": "builtin", + } + + # Update goose configuration with model and provider from environment variables + goose_model = os.environ.get("MC_MODEL") + goose_provider = os.environ.get("MC_PROVIDER") + + if goose_model: + config_data["GOOSE_MODEL"] = goose_model + print(f"Set GOOSE_MODEL to {goose_model}") + + if goose_provider: + config_data["GOOSE_PROVIDER"] = goose_provider + print(f"Set GOOSE_PROVIDER to {goose_provider}") + # Get MCP information from environment variables mcp_count = int(os.environ.get("MCP_COUNT", "0")) mcp_names_str = os.environ.get("MCP_NAMES", "[]") diff --git a/mcontainer/models.py b/mcontainer/models.py index 1580931..8a07c2f 100644 --- a/mcontainer/models.py +++ b/mcontainer/models.py @@ -104,11 +104,13 @@ class Session(BaseModel): project: Optional[str] = None created_at: str ports: Dict[int, int] = Field(default_factory=dict) - mcps: List[str] = Field(default_factory=list) # List of MCP server names - run_command: Optional[str] = None # Command executed on start - uid: Optional[int] = None # Store UID used - gid: Optional[int] = None # Store GID used - ssh: bool = False # Whether SSH server is enabled + mcps: List[str] = Field(default_factory=list) + run_command: Optional[str] = None + uid: Optional[int] = None + gid: Optional[int] = None + model: Optional[str] = None + provider: Optional[str] = None + ssh: bool = False class Config(BaseModel): diff --git a/mcontainer/user_config.py b/mcontainer/user_config.py index f52fa59..8450a7a 100644 --- a/mcontainer/user_config.py +++ b/mcontainer/user_config.py @@ -94,6 +94,8 @@ class UserConfigManager: "networks": [], # Default networks to connect to (besides mc-network) "volumes": [], # Default volumes to mount, format: "source:dest" "mcps": [], # Default MCP servers to connect to + "model": "claude-3-5-sonnet-latest", # Default LLM model to use + "provider": "anthropic", # Default LLM provider to use }, "services": { "langfuse": {},