160 lines
5.2 KiB
Bash
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
|