blob: 15095bd9c2176760b9c06d14ffb2ee9136c742ad (
plain) (
tree)
|
|
#!/bin/bash
# Makima Orchestrator Helper Script
# Usage: ./orchestrate.sh <command> [args...]
API_URL="${MAKIMA_API_URL:-http://localhost:8080}"
API_KEY="${MAKIMA_API_KEY}"
TASK_ID="${MAKIMA_TASK_ID}"
if [ -z "$API_KEY" ]; then
echo "Error: MAKIMA_API_KEY not set" >&2
exit 1
fi
if [ -z "$TASK_ID" ]; then
echo "Error: MAKIMA_TASK_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
list)
api_call GET "$API_URL/api/v1/mesh/tasks/$TASK_ID/subtasks"
;;
create)
# Parse arguments: create "name" "plan" [--continue-from <task_id>] [--files "file1,file2"]
if [ -z "$2" ] || [ -z "$3" ]; then
echo "Usage: $0 create \"<name>\" \"<plan>\" [--continue-from <task_id>] [--files \"file1,file2\"]" >&2
exit 1
fi
NAME="$2"
PLAN="$3"
CONTINUE_FROM=""
COPY_FILES=""
# Parse optional flags (can be in any order after name and plan)
shift 3
while [ $# -gt 0 ]; do
case "$1" in
--continue-from)
CONTINUE_FROM="$2"
shift 2
;;
--files)
COPY_FILES="$2"
shift 2
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# Escape quotes in name and plan for JSON
NAME_ESCAPED=$(echo "$NAME" | sed 's/"/\\"/g' | sed 's/\\/\\\\/g')
PLAN_ESCAPED=$(echo "$PLAN" | sed 's/"/\\"/g' | sed 's/\\/\\\\/g')
# Build JSON body
JSON_BODY="{\"name\":\"$NAME_ESCAPED\",\"plan\":\"$PLAN_ESCAPED\",\"parentTaskId\":\"$TASK_ID\""
if [ -n "$CONTINUE_FROM" ]; then
echo "Creating subtask: $NAME (continuing from $CONTINUE_FROM)..." >&2
JSON_BODY="$JSON_BODY,\"continueFromTaskId\":\"$CONTINUE_FROM\""
else
echo "Creating subtask: $NAME..." >&2
fi
if [ -n "$COPY_FILES" ]; then
# Convert comma-separated file list to JSON array
FILES_JSON="["
first=true
IFS=',' read -ra FILE_ARRAY <<< "$COPY_FILES"
for file in "${FILE_ARRAY[@]}"; do
file=$(echo "$file" | xargs) # trim whitespace
if [ "$first" = true ]; then
FILES_JSON="$FILES_JSON\"$file\""
first=false
else
FILES_JSON="$FILES_JSON,\"$file\""
fi
done
FILES_JSON="$FILES_JSON]"
JSON_BODY="$JSON_BODY,\"copyFiles\":$FILES_JSON"
echo " (copying files: $COPY_FILES)" >&2
fi
JSON_BODY="$JSON_BODY}"
api_call POST "$API_URL/api/v1/mesh/tasks" "$JSON_BODY"
;;
start)
if [ -z "$2" ]; then
echo "Usage: $0 start <subtask_id>" >&2
exit 1
fi
echo "Starting subtask $2..." >&2
api_call POST "$API_URL/api/v1/mesh/tasks/$2/start"
;;
stop)
if [ -z "$2" ]; then
echo "Usage: $0 stop <subtask_id>" >&2
exit 1
fi
api_call POST "$API_URL/api/v1/mesh/tasks/$2/stop"
;;
status)
if [ -z "$2" ]; then
echo "Usage: $0 status <subtask_id>" >&2
exit 1
fi
api_call GET "$API_URL/api/v1/mesh/tasks/$2"
;;
output)
if [ -z "$2" ]; then
echo "Usage: $0 output <subtask_id>" >&2
exit 1
fi
api_call GET "$API_URL/api/v1/mesh/tasks/$2/output"
;;
worktree)
if [ -z "$2" ]; then
echo "Usage: $0 worktree <subtask_id>" >&2
exit 1
fi
# Get the worktree path from the task's overlayPath field via API
TASK_JSON=$(api_call GET "$API_URL/api/v1/mesh/tasks/$2")
if [ $? -ne 0 ]; then
echo "Error: Failed to get task info" >&2
exit 1
fi
WORKTREE_PATH=$(echo "$TASK_JSON" | grep -o '"overlayPath":"[^"]*"' | cut -d'"' -f4)
if [ -z "$WORKTREE_PATH" ]; then
echo "Error: Task has no worktree path (may not have started yet)" >&2
exit 1
fi
if [ -d "$WORKTREE_PATH" ]; then
echo "$WORKTREE_PATH"
else
echo "Error: Worktree not found at $WORKTREE_PATH" >&2
echo "The worktree may have been cleaned up." >&2
exit 1
fi
;;
done)
SUMMARY="${2:-Task completed}"
api_call PUT "$API_URL/api/v1/mesh/tasks/$TASK_ID" "{\"status\":\"done\",\"progressSummary\":\"$SUMMARY\"}"
;;
*)
echo "Makima Orchestrator Helper"
echo ""
echo "Usage: $0 <command> [args...]"
echo ""
echo "Subtask Commands:"
echo " list List all subtasks and their status"
echo " create \"<name>\" \"<plan>\" Create a new subtask"
echo " create \"...\" --continue-from ID Create subtask continuing from another task's worktree"
echo " create \"...\" --files \"file1,file2\" Copy specific files from parent (orchestrator) worktree"
echo " start <subtask_id> Start a subtask"
echo " stop <subtask_id> Stop a running subtask"
echo " status <subtask_id> Get detailed subtask status"
echo " output <subtask_id> Get subtask output history"
echo " worktree <subtask_id> Get path to subtask's worktree"
echo ""
echo "Completion:"
echo " done [summary] Mark orchestrator as complete"
echo ""
echo "Examples:"
echo " create \"Fix bug\" \"Fix the null check bug\" --files \"PLAN.md\""
echo " create \"Step 2\" \"Continue work\" --continue-from abc123 --files \"shared.rs,types.rs\""
;;
esac
|