summaryrefslogblamecommitdiff
path: root/.makima/supervisor.sh
blob: 5a1693ee87a98b5ce727aedc1482bd25d449fece (plain) (tree)















































































































































































































































































































                                                                                                                                    
#!/bin/bash
# Makima Supervisor Helper Script
# Usage: ./supervisor.sh <command> [args...]

API_URL="${MAKIMA_API_URL:-http://localhost:8080}"
API_KEY="${MAKIMA_API_KEY}"
TASK_ID="${MAKIMA_TASK_ID}"
CONTRACT_ID="${MAKIMA_CONTRACT_ID}"

if [ -z "$API_KEY" ]; then
    echo "Error: MAKIMA_API_KEY not set" >&2
    exit 1
fi

if [ -z "$CONTRACT_ID" ]; then
    echo "Error: MAKIMA_CONTRACT_ID not set" >&2
    exit 1
fi

# Helper function to make API calls and check for errors
api_call() {
    local method="$1"
    local url="$2"
    local data="$3"
    local response
    local http_code

    if [ -n "$data" ]; then
        response=$(curl -s -w "\n%{http_code}" -X "$method" \
            -H "X-Makima-Tool-Key: $API_KEY" \
            -H "Content-Type: application/json" \
            -d "$data" \
            "$url")
    else
        response=$(curl -s -w "\n%{http_code}" -X "$method" \
            -H "X-Makima-Tool-Key: $API_KEY" \
            "$url")
    fi

    # Extract HTTP code (last line) and body (everything else)
    http_code=$(echo "$response" | tail -n1)
    body=$(echo "$response" | sed '$d')

    # Check for curl errors or non-2xx status
    if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
        echo "Error: API request failed with HTTP $http_code" >&2
        echo "URL: $url" >&2
        echo "Response: $body" >&2
        echo "$body"
        return 1
    fi

    echo "$body"
    return 0
}

case "$1" in
    tasks)
        # Get all tasks in this contract's tree
        api_call GET "$API_URL/api/v1/mesh/supervisor/contracts/$CONTRACT_ID/tasks"
        ;;
    tree)
        # Get full task tree structure
        api_call GET "$API_URL/api/v1/mesh/supervisor/contracts/$CONTRACT_ID/tree"
        ;;
    spawn)
        # Create a new task (fire and forget)
        if [ -z "$2" ] || [ -z "$3" ]; then
            echo "Usage: $0 spawn \"<name>\" \"<plan>\" [--parent <task_id>] [--checkpoint <sha>]" >&2
            exit 1
        fi
        NAME="$2"
        PLAN="$3"
        PARENT_ID=""
        CHECKPOINT_SHA=""

        shift 3
        while [ $# -gt 0 ]; do
            case "$1" in
                --parent)
                    PARENT_ID="$2"
                    shift 2
                    ;;
                --checkpoint)
                    CHECKPOINT_SHA="$2"
                    shift 2
                    ;;
                *)
                    echo "Unknown option: $1" >&2
                    exit 1
                    ;;
            esac
        done

        # Escape for JSON: backslashes first, then quotes, then newlines
        NAME_ESCAPED=$(printf '%s' "$NAME" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
        PLAN_ESCAPED=$(printf '%s' "$PLAN" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')

        # Build JSON body
        JSON_BODY="{\"name\":\"$NAME_ESCAPED\",\"plan\":\"$PLAN_ESCAPED\",\"contractId\":\"$CONTRACT_ID\""
        if [ -n "$PARENT_ID" ]; then
            JSON_BODY="$JSON_BODY,\"parentTaskId\":\"$PARENT_ID\""
        fi
        if [ -n "$CHECKPOINT_SHA" ]; then
            JSON_BODY="$JSON_BODY,\"checkpointSha\":\"$CHECKPOINT_SHA\""
        fi
        JSON_BODY="$JSON_BODY}"

        echo "Creating task: $NAME..." >&2
        api_call POST "$API_URL/api/v1/mesh/supervisor/tasks" "$JSON_BODY"
        ;;
    wait)
        # Wait for a task to complete
        if [ -z "$2" ]; then
            echo "Usage: $0 wait <task_id> [timeout_seconds]" >&2
            exit 1
        fi
        WAIT_TASK_ID="$2"
        TIMEOUT="${3:-300}"

        echo "Waiting for task $WAIT_TASK_ID (timeout: ${TIMEOUT}s)..." >&2
        api_call POST "$API_URL/api/v1/mesh/supervisor/tasks/$WAIT_TASK_ID/wait" "{\"timeoutSeconds\":$TIMEOUT}"
        ;;
    read-file)
        # Read a file from any task's worktree
        if [ -z "$2" ] || [ -z "$3" ]; then
            echo "Usage: $0 read-file <task_id> <file_path>" >&2
            exit 1
        fi
        READ_TASK_ID="$2"
        FILE_PATH="$3"
        FILE_PATH_ESCAPED=$(echo "$FILE_PATH" | sed 's/"/\\"/g')

        api_call POST "$API_URL/api/v1/mesh/supervisor/tasks/$READ_TASK_ID/read-file" "{\"filePath\":\"$FILE_PATH_ESCAPED\"}"
        ;;
    checkpoint)
        # Create a git checkpoint
        if [ -z "$2" ]; then
            echo "Usage: $0 checkpoint \"<message>\"" >&2
            exit 1
        fi
        MESSAGE_ESCAPED=$(printf '%s' "$2" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
        api_call POST "$API_URL/api/v1/mesh/tasks/$TASK_ID/checkpoint" "{\"message\":\"$MESSAGE_ESCAPED\"}"
        ;;
    checkpoints)
        # List checkpoints for a task
        CHECK_TASK_ID="${2:-$TASK_ID}"
        api_call GET "$API_URL/api/v1/mesh/tasks/$CHECK_TASK_ID/checkpoints"
        ;;
    status)
        # Get contract status
        api_call GET "$API_URL/api/v1/contracts/$CONTRACT_ID/daemon/status"
        ;;
    branch)
        # Create a new branch
        if [ -z "$2" ]; then
            echo "Usage: $0 branch <branch_name> [--from <task_id|sha>]" >&2
            exit 1
        fi
        BRANCH_NAME="$2"
        FROM_REF=""
        shift 2
        while [ $# -gt 0 ]; do
            case "$1" in
                --from)
                    FROM_REF="$2"
                    shift 2
                    ;;
                *)
                    echo "Unknown option: $1" >&2
                    exit 1
                    ;;
            esac
        done
        JSON_BODY="{\"branchName\":\"$BRANCH_NAME\""
        if [ -n "$FROM_REF" ]; then
            JSON_BODY="$JSON_BODY,\"fromRef\":\"$FROM_REF\""
        fi
        JSON_BODY="$JSON_BODY}"
        echo "Creating branch: $BRANCH_NAME..." >&2
        api_call POST "$API_URL/api/v1/mesh/supervisor/branches" "$JSON_BODY"
        ;;
    merge)
        # Merge a task's changes to a branch
        if [ -z "$2" ]; then
            echo "Usage: $0 merge <task_id> [--to <branch>] [--squash]" >&2
            exit 1
        fi
        MERGE_TASK_ID="$2"
        TARGET_BRANCH=""
        SQUASH="false"
        shift 2
        while [ $# -gt 0 ]; do
            case "$1" in
                --to)
                    TARGET_BRANCH="$2"
                    shift 2
                    ;;
                --squash)
                    SQUASH="true"
                    shift
                    ;;
                *)
                    echo "Unknown option: $1" >&2
                    exit 1
                    ;;
            esac
        done
        JSON_BODY="{\"squash\":$SQUASH"
        if [ -n "$TARGET_BRANCH" ]; then
            JSON_BODY="$JSON_BODY,\"targetBranch\":\"$TARGET_BRANCH\""
        fi
        JSON_BODY="$JSON_BODY}"
        echo "Merging task $MERGE_TASK_ID..." >&2
        api_call POST "$API_URL/api/v1/mesh/supervisor/tasks/$MERGE_TASK_ID/merge" "$JSON_BODY"
        ;;
    pr)
        # Create a pull request
        if [ -z "$2" ]; then
            echo "Usage: $0 pr <task_id> --title \"Title\" [--body \"Body\"] [--base main]" >&2
            exit 1
        fi
        PR_TASK_ID="$2"
        PR_TITLE=""
        PR_BODY=""
        PR_BASE="main"
        shift 2
        while [ $# -gt 0 ]; do
            case "$1" in
                --title)
                    PR_TITLE="$2"
                    shift 2
                    ;;
                --body)
                    PR_BODY="$2"
                    shift 2
                    ;;
                --base)
                    PR_BASE="$2"
                    shift 2
                    ;;
                *)
                    echo "Unknown option: $1" >&2
                    exit 1
                    ;;
            esac
        done
        if [ -z "$PR_TITLE" ]; then
            echo "Error: --title is required" >&2
            exit 1
        fi
        TITLE_ESCAPED=$(printf '%s' "$PR_TITLE" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
        BODY_ESCAPED=$(printf '%s' "$PR_BODY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
        JSON_BODY="{\"taskId\":\"$PR_TASK_ID\",\"title\":\"$TITLE_ESCAPED\",\"body\":\"$BODY_ESCAPED\",\"baseBranch\":\"$PR_BASE\"}"
        echo "Creating PR for task $PR_TASK_ID..." >&2
        api_call POST "$API_URL/api/v1/mesh/supervisor/pr" "$JSON_BODY"
        ;;
    diff)
        # Get diff for a task
        if [ -z "$2" ]; then
            echo "Usage: $0 diff <task_id>" >&2
            exit 1
        fi
        DIFF_TASK_ID="$2"
        api_call GET "$API_URL/api/v1/mesh/supervisor/tasks/$DIFF_TASK_ID/diff"
        ;;
    *)
        echo "Makima Supervisor Helper"
        echo ""
        echo "Usage: $0 <command> [args...]"
        echo ""
        echo "Task Management:"
        echo "  tasks                               List all tasks in contract tree"
        echo "  tree                                Get full task tree structure"
        echo "  spawn \"<name>\" \"<plan>\"             Create and start a new task"
        echo "    --parent <task_id>                  Parent task to branch from"
        echo "    --checkpoint <sha>                  Checkpoint to start from"
        echo "  wait <task_id> [timeout]            Wait for task completion"
        echo "  read-file <task_id> <path>          Read file from task's worktree"
        echo ""
        echo "Git Operations:"
        echo "  branch <name> [--from <ref>]        Create a new branch"
        echo "  merge <task_id> [--to <branch>]     Merge task changes"
        echo "    --squash                            Squash commits on merge"
        echo "  pr <task_id> --title \"Title\"        Create a pull request"
        echo "    --body \"Body\"                       PR description"
        echo "    --base <branch>                     Target branch (default: main)"
        echo "  diff <task_id>                      View task's diff"
        echo ""
        echo "Checkpoints:"
        echo "  checkpoint \"<message>\"              Create git checkpoint"
        echo "  checkpoints [task_id]               List task checkpoints"
        echo ""
        echo "Contract:"
        echo "  status                              Get contract status"
        echo ""
        echo "Examples:"
        echo "  $0 tasks"
        echo "  $0 spawn \"Implement auth\" \"Add user authentication system\""
        echo "  $0 wait abc12345 600"
        echo "  $0 merge abc12345 --to main --squash"
        echo "  $0 pr abc12345 --title \"Add auth\" --base main"
        ;;
esac