fix(goose): rename mai to mc, add initialization status

This commit is contained in:
2025-03-10 23:44:09 -06:00
parent 08ba1ab2da
commit 74c723db7b
7 changed files with 182 additions and 17 deletions

View File

@@ -20,16 +20,21 @@ RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/
# Create app directory
WORKDIR /app
# Install python dependencies
# This is done before copying scripts for better cache management
RUN pip install --no-cache-dir goose-ai langfuse
# Copy initialization scripts
COPY mai-init.sh /mai-init.sh
COPY mc-init.sh /mc-init.sh
COPY entrypoint.sh /entrypoint.sh
COPY mai-driver.yaml /mai-driver.yaml
COPY mc-driver.yaml /mc-driver.yaml
COPY init-status.sh /init-status.sh
# Make scripts executable
RUN chmod +x /mai-init.sh /entrypoint.sh
RUN chmod +x /mc-init.sh /entrypoint.sh /init-status.sh
# Install python dependencies
RUN pip install --no-cache-dir goose-ai langfuse
# Set up initialization status check on login
RUN echo '[ -x /init-status.sh ] && /init-status.sh' >> /etc/bash.bashrc
# Set up environment
ENV PYTHONUNBUFFERED=1

View File

@@ -2,7 +2,7 @@
# Entrypoint script for Goose driver
# Run the standard initialization script
/mai-init.sh
/mc-init.sh
# Start SSH server in the background
/usr/sbin/sshd

View File

@@ -0,0 +1,65 @@
#!/bin/bash
# Script to check and display initialization status
# Function to display initialization logs
show_init_logs() {
if [ -f "/init.log" ]; then
echo "Displaying initialization logs:"
echo "----------------------------------------"
cat /init.log
echo "----------------------------------------"
else
echo "No initialization logs found."
fi
}
# Function to follow logs until initialization completes
follow_init_logs() {
if [ ! -f "/init.log" ]; then
echo "No initialization logs found."
return
fi
echo "Initialization is still in progress. Showing logs:"
echo "----------------------------------------"
tail -f /init.log &
tail_pid=$!
# Check every second if initialization has completed
while true; do
if [ -f "/init.status" ] && grep -q "INIT_COMPLETE=true" "/init.status"; then
kill $tail_pid 2>/dev/null
echo "----------------------------------------"
echo "Initialization completed."
break
fi
sleep 1
done
}
# Check if we're in an interactive shell
if [ -t 0 ]; then
INTERACTIVE=true
else
INTERACTIVE=false
fi
# Check initialization status
if [ -f "/init.status" ]; then
if grep -q "INIT_COMPLETE=true" "/init.status"; then
echo "MC initialization has completed."
# No longer prompt to show logs when initialization is complete
else
echo "MC initialization is still in progress."
follow_init_logs
fi
else
echo "Cannot determine initialization status."
# Ask if user wants to see logs if they exist (only in interactive mode)
if [ -f "/init.log" ] && [ "$INTERACTIVE" = true ]; then
read -p "Do you want to see initialization logs? (y/n): " show_logs
if [[ "$show_logs" =~ ^[Yy] ]]; then
show_init_logs
fi
fi
fi

View File

@@ -4,7 +4,7 @@ version: 1.0.0
maintainer: team@monadical.com
init:
pre_command: /mai-init.sh
pre_command: /mc-init.sh
command: /entrypoint.sh
environment:

View File

@@ -1,6 +1,13 @@
#!/bin/bash
# Standardized initialization script for MC drivers
# Redirect all output to both stdout and the log file
exec > >(tee -a /init.log) 2>&1
# Mark initialization as started
echo "=== MC Initialization started at $(date) ==="
echo "INIT_COMPLETE=false" > /init.status
# Project initialization
if [ -n "$MC_PROJECT_URL" ]; then
echo "Initializing project: $MC_PROJECT_URL"
@@ -51,4 +58,8 @@ if [ -n "$LANGFUSE_SECRET_KEY" ] && [ -n "$LANGFUSE_PUBLIC_KEY" ]; then
export LANGFUSE_HOST="${LANGFUSE_HOST:-https://api.langfuse.com}"
fi
echo "MC driver initialization complete"
echo "MC driver initialization complete"
# Mark initialization as complete
echo "=== MC Initialization completed at $(date) ==="
echo "INIT_COMPLETE=true" > /init.status

View File

@@ -104,7 +104,9 @@ def create_session(
False, "--no-connect", help="Don't automatically connect to the session"
),
no_mount: bool = typer.Option(
False, "--no-mount", help="Don't mount local directory to /app"
False,
"--no-mount",
help="Don't mount local directory to /app (ignored if --project is used)",
),
) -> None:
"""Create a new MC session"""
@@ -216,15 +218,33 @@ def connect_session(
def session_logs(
session_id: str = typer.Argument(..., help="Session ID to get logs from"),
follow: bool = typer.Option(False, "--follow", "-f", help="Follow log output"),
init: bool = typer.Option(
False, "--init", "-i", help="Show initialization logs instead of container logs"
),
) -> None:
"""Stream logs from a MC session"""
if follow:
console.print(f"Streaming logs from session {session_id}... (Ctrl+C to exit)")
container_manager.get_session_logs(session_id, follow=True)
if init:
# Show initialization logs
if follow:
console.print(
f"Streaming initialization logs from session {session_id}... (Ctrl+C to exit)"
)
container_manager.get_init_logs(session_id, follow=True)
else:
logs = container_manager.get_init_logs(session_id)
if logs:
console.print(logs)
else:
logs = container_manager.get_session_logs(session_id)
if logs:
console.print(logs)
# Show regular container logs
if follow:
console.print(
f"Streaming logs from session {session_id}... (Ctrl+C to exit)"
)
container_manager.get_session_logs(session_id, follow=True)
else:
logs = container_manager.get_session_logs(session_id)
if logs:
console.print(logs)
@app.command()
@@ -255,7 +275,9 @@ def quick_create(
False, "--no-connect", help="Don't automatically connect to the session"
),
no_mount: bool = typer.Option(
False, "--no-mount", help="Don't mount local directory to /app"
False,
"--no-mount",
help="Don't mount local directory to /app (ignored if a project is specified)",
),
) -> None:
"""Create a new MC session with a project repository"""

View File

@@ -119,6 +119,10 @@ class ContainerManager:
# Prepare environment variables
env_vars = environment or {}
# Add project URL to environment if provided
if project:
env_vars["MC_PROJECT_URL"] = project
# Pull image if needed
try:
self.client.images.get(driver.image)
@@ -128,13 +132,19 @@ class ContainerManager:
# Set up volume mounts
volumes = {}
if mount_local:
# If project URL is provided, don't mount local directory (will clone into /app)
# If no project URL and mount_local is True, mount local directory to /app
if not project and mount_local:
# Mount current directory to /app in the container
import os
current_dir = os.getcwd()
volumes[current_dir] = {"bind": "/app", "mode": "rw"}
print(f"Mounting local directory {current_dir} to /app")
elif project:
print(
f"Project URL provided - container will clone {project} into /app during initialization"
)
# Create container
container = self.client.containers.create(
@@ -220,6 +230,8 @@ class ContainerManager:
return False
# Execute interactive shell in container
# The init-status.sh script will automatically show logs if needed
print(f"Connecting to session {session_id}...")
os.system(f"docker exec -it {session.container_id} /bin/bash")
return True
@@ -345,3 +357,53 @@ class ContainerManager:
except DockerException as e:
print(f"Error getting session logs: {e}")
return None
def get_init_logs(self, session_id: str, follow: bool = False) -> Optional[str]:
"""Get initialization logs from a MC session
Args:
session_id: The session ID
follow: Whether to follow the logs
Returns:
The logs as a string, or None if there was an error
"""
try:
sessions = self.list_sessions()
for session in sessions:
if session.id == session_id and session.container_id:
container = self.client.containers.get(session.container_id)
# Check if initialization is complete
init_complete = False
try:
exit_code, output = container.exec_run(
"grep -q 'INIT_COMPLETE=true' /init.status"
)
init_complete = exit_code == 0
except DockerException:
pass
if follow and not init_complete:
print(
f"Following initialization logs for session {session_id}..."
)
print("Press Ctrl+C to stop following")
container.exec_run(
"tail -f /init.log", stream=True, demux=True, tty=True
)
return None
else:
exit_code, output = container.exec_run("cat /init.log")
if exit_code == 0:
return output.decode()
else:
print("No initialization logs found")
return None
print(f"Session '{session_id}' not found")
return None
except DockerException as e:
print(f"Error getting initialization logs: {e}")
return None