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
|