Files
2026-06-08 22:52:12 +10:00

160 lines
5.2 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
###############################################################################
# entrypoint.sh - Base entrypoint for forgebot AI agent containers
###############################################################################
# ---------------------------------------------------------------------------
# Required environment variables
# ---------------------------------------------------------------------------
REQUIRED_VARS=(
FORGEBOT_REPO
FORGEBOT_REF
FORGEBOT_COMMAND
FORGEBOT_API_URL
FORGEBOT_TASK_ID
ANTHROPIC_API_KEY
)
for var in "${REQUIRED_VARS[@]}"; do
if [[ -z "${!var:-}" ]]; then
echo "FATAL: required env var $var is not set" >&2
exit 1
fi
done
# ---------------------------------------------------------------------------
# Defaults
# ---------------------------------------------------------------------------
export ANTHROPIC_BASE_URL="${ANTHROPIC_BASE_URL:-https://litellm.k8s.syd1.au.unkin.net}"
export GITEA_URL="${GITEA_URL:-https://git.unkin.net}"
FORGEBOT_MODEL="${FORGEBOT_MODEL:-claude-sonnet-4-20250514}"
# ---------------------------------------------------------------------------
# Helper functions
# ---------------------------------------------------------------------------
# Report task status back to the forgebot API.
# report_status <status> <message>
report_status() {
local status="$1"
local message="$2"
curl -sf -X PATCH \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${FORGEBOT_TASK_ID}" \
-d "$(jq -n --arg s "$status" --arg m "$message" '{status: $s, message: $m}')" \
|| echo "WARNING: failed to report status '$status'" >&2
}
# Create a subtask. Reads JSON body from stdin or from the first argument.
# echo '{"kind":"review",...}' | create_subtask
# create_subtask '{"kind":"review",...}'
create_subtask() {
local body
if [[ $# -gt 0 ]]; then
body="$1"
else
body="$(cat)"
fi
curl -sf -X POST \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks" \
-d "$body"
}
# Check the status of a task by ID.
# check_task <task_id>
check_task() {
local task_id="$1"
curl -sf -X GET \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${task_id}"
}
# Post a comment on the current task.
# post_comment <message>
post_comment() {
local message="$1"
curl -sf -X POST \
-H "Content-Type: application/json" \
"${FORGEBOT_API_URL}/tasks/${FORGEBOT_TASK_ID}/comment" \
-d "$(jq -n --arg m "$message" '{message: $m}')"
}
# ---------------------------------------------------------------------------
# Clone & checkout
# ---------------------------------------------------------------------------
REPO_DIR="/home/agent/workspace"
echo "Cloning ${FORGEBOT_REPO} ..."
git clone "${GITEA_URL}/${FORGEBOT_REPO}.git" "$REPO_DIR"
cd "$REPO_DIR"
echo "Checking out ref ${FORGEBOT_REF} ..."
git checkout "${FORGEBOT_REF}"
# ---------------------------------------------------------------------------
# Extra tools (optional)
# ---------------------------------------------------------------------------
if [[ -n "${FORGEBOT_EXTRA_TOOLS:-}" ]]; then
echo "Downloading extra tools: ${FORGEBOT_EXTRA_TOOLS}"
mkdir -p /home/agent/bin
export PATH="/home/agent/bin:${PATH}"
IFS=',' read -ra TOOLS <<< "$FORGEBOT_EXTRA_TOOLS"
for tool in "${TOOLS[@]}"; do
tool="$(echo "$tool" | xargs)" # trim whitespace
echo " -> fetching $tool"
curl -sf -o "/home/agent/bin/${tool}" \
"${FORGEBOT_API_URL}/tools/${tool}" \
&& chmod +x "/home/agent/bin/${tool}" \
|| echo "WARNING: failed to download tool '${tool}'" >&2
done
fi
# ---------------------------------------------------------------------------
# Load skill (optional configmap mount)
# ---------------------------------------------------------------------------
SKILL_CONTEXT=""
if [[ -n "${FORGEBOT_SKILL:-}" && -f "/skills/${FORGEBOT_SKILL}/SKILL.md" ]]; then
echo "Loading skill: ${FORGEBOT_SKILL}"
SKILL_CONTEXT="$(cat "/skills/${FORGEBOT_SKILL}/SKILL.md")"
fi
# ---------------------------------------------------------------------------
# Build the prompt
# ---------------------------------------------------------------------------
PROMPT="${FORGEBOT_COMMAND}"
if [[ -n "$SKILL_CONTEXT" ]]; then
PROMPT="$(printf '%s\n\n---\n\n%s' "$SKILL_CONTEXT" "$PROMPT")"
fi
# ---------------------------------------------------------------------------
# Run claude
# ---------------------------------------------------------------------------
report_status "running" "Agent started, executing command"
set +e
RESULT="$(claude \
--model "$FORGEBOT_MODEL" \
--print \
--dangerously-skip-permissions \
<<< "$PROMPT" 2>&1)"
EXIT_CODE=$?
set -e
# ---------------------------------------------------------------------------
# Report result
# ---------------------------------------------------------------------------
if [[ $EXIT_CODE -eq 0 ]]; then
echo "Agent completed successfully."
report_status "completed" "$RESULT"
else
echo "Agent failed with exit code ${EXIT_CODE}." >&2
report_status "failed" "Exit code ${EXIT_CODE}: ${RESULT}"
fi
exit $EXIT_CODE