Initial claude skill with skills access
This commit is contained in:
175
scripts/run.sh
Normal file
175
scripts/run.sh
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SKILL_DIR="$(dirname "$(dirname "$0")")"
|
||||
CLAUDE_PORT="${CLAUDE_PORT:-8888}"
|
||||
CLAUDE_MODEL="${CLAUDE_MODEL:-claude-sonnet-4-20250514}"
|
||||
CLAUDE_MAX_TURNS="${CLAUDE_MAX_TURNS:-10}"
|
||||
SKILLS_DIR="${SKILLS_DIR:-/skills}"
|
||||
SYSTEM_PROMPT_FILE="$SKILL_DIR/prompts/system.md"
|
||||
|
||||
# Create HTTP handler
|
||||
create_handler() {
|
||||
cat > /tmp/claude_handler.sh << 'HANDLER'
|
||||
#!/bin/bash
|
||||
|
||||
SKILL_DIR="${SKILL_DIR}"
|
||||
CLAUDE_MODEL="${CLAUDE_MODEL:-claude-sonnet-4-20250514}"
|
||||
CLAUDE_MAX_TURNS="${CLAUDE_MAX_TURNS:-10}"
|
||||
SKILLS_DIR="${SKILLS_DIR:-/skills}"
|
||||
SYSTEM_PROMPT_FILE="${SYSTEM_PROMPT_FILE}"
|
||||
|
||||
# Read HTTP request
|
||||
read -r request_line
|
||||
method=$(echo "$request_line" | cut -d' ' -f1)
|
||||
path=$(echo "$request_line" | cut -d' ' -f2)
|
||||
|
||||
# Read headers
|
||||
content_length=0
|
||||
while read -r header; do
|
||||
header=$(echo "$header" | tr -d '\r')
|
||||
[ -z "$header" ] && break
|
||||
if [[ "$header" =~ ^[Cc]ontent-[Ll]ength:\ *([0-9]+) ]]; then
|
||||
content_length="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Read body
|
||||
body=""
|
||||
if [ "$content_length" -gt 0 ]; then
|
||||
body=$(head -c "$content_length")
|
||||
fi
|
||||
|
||||
# Response helper
|
||||
send_response() {
|
||||
local status="$1"
|
||||
local content_type="$2"
|
||||
local body="$3"
|
||||
local body_length=${#body}
|
||||
|
||||
printf "HTTP/1.1 %s\r\n" "$status"
|
||||
printf "Content-Type: %s\r\n" "$content_type"
|
||||
printf "Content-Length: %d\r\n" "$body_length"
|
||||
printf "Connection: close\r\n"
|
||||
printf "\r\n"
|
||||
printf "%s" "$body"
|
||||
}
|
||||
|
||||
# Health check
|
||||
if [ "$path" = "/health" ]; then
|
||||
if command -v claude &>/dev/null; then
|
||||
send_response "200 OK" "application/json" '{"status":"ok","claude":"available"}'
|
||||
else
|
||||
send_response "503 Service Unavailable" "application/json" '{"status":"error","claude":"not found"}'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Execute endpoint (one-shot)
|
||||
if [ "$path" = "/execute" ] && [ "$method" = "POST" ]; then
|
||||
prompt=$(echo "$body" | jq -r '.prompt // empty')
|
||||
|
||||
if [ -z "$prompt" ]; then
|
||||
send_response "400 Bad Request" "application/json" '{"error":"Missing prompt field"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build claude command
|
||||
cd "$SKILLS_DIR"
|
||||
|
||||
# Run claude with system prompt
|
||||
result=$(claude --print \
|
||||
--model "$CLAUDE_MODEL" \
|
||||
--max-turns "$CLAUDE_MAX_TURNS" \
|
||||
--system-prompt "$(cat "$SYSTEM_PROMPT_FILE")" \
|
||||
--allowedTools "Bash,Read,Write,Edit,Glob,Grep" \
|
||||
"$prompt" 2>&1) || {
|
||||
error_msg=$(echo "$result" | jq -Rs '.')
|
||||
send_response "500 Internal Server Error" "application/json" "{\"success\":false,\"error\":$error_msg}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Return result
|
||||
result_json=$(echo "$result" | jq -Rs '.')
|
||||
send_response "200 OK" "application/json" "{\"success\":true,\"result\":$result_json}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Chat endpoint (simplified, non-streaming for now)
|
||||
if [ "$path" = "/chat" ] && [ "$method" = "POST" ]; then
|
||||
message=$(echo "$body" | jq -r '.message // empty')
|
||||
session_id=$(echo "$body" | jq -r '.session_id // empty')
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
send_response "400 Bad Request" "application/json" '{"error":"Missing message field"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$SKILLS_DIR"
|
||||
|
||||
# Build command
|
||||
claude_args=(
|
||||
"--print"
|
||||
"--model" "$CLAUDE_MODEL"
|
||||
"--max-turns" "1"
|
||||
"--system-prompt" "$(cat "$SYSTEM_PROMPT_FILE")"
|
||||
"--allowedTools" "Bash,Read,Write,Edit,Glob,Grep"
|
||||
)
|
||||
|
||||
# Resume session if provided
|
||||
if [ -n "$session_id" ]; then
|
||||
claude_args+=("--resume" "$session_id")
|
||||
fi
|
||||
|
||||
result=$(claude "${claude_args[@]}" "$message" 2>&1) || {
|
||||
error_msg=$(echo "$result" | jq -Rs '.')
|
||||
send_response "500 Internal Server Error" "application/json" "{\"success\":false,\"error\":$error_msg}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
result_json=$(echo "$result" | jq -Rs '.')
|
||||
send_response "200 OK" "application/json" "{\"success\":true,\"response\":$result_json}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Skills list
|
||||
if [ "$path" = "/skills" ] && [ "$method" = "GET" ]; then
|
||||
skills="[]"
|
||||
for skill_dir in "$SKILLS_DIR"/*/; do
|
||||
skill_name=$(basename "$skill_dir")
|
||||
skill_md="$skill_dir/SKILL.md"
|
||||
if [ -f "$skill_md" ]; then
|
||||
desc=$(yq -r '.description // "No description"' < <(sed -n '/^---$/,/^---$/p' "$skill_md" | sed '1d;$d') 2>/dev/null || echo "")
|
||||
skills=$(echo "$skills" | jq --arg name "$skill_name" --arg desc "$desc" '. + [{"name":$name,"description":$desc}]')
|
||||
fi
|
||||
done
|
||||
send_response "200 OK" "application/json" "$skills"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Not found
|
||||
send_response "404 Not Found" "application/json" '{"error":"Endpoints: POST /execute, POST /chat, GET /skills, GET /health"}'
|
||||
HANDLER
|
||||
|
||||
chmod +x /tmp/claude_handler.sh
|
||||
|
||||
# Export vars for handler
|
||||
export SKILL_DIR
|
||||
export CLAUDE_MODEL
|
||||
export CLAUDE_MAX_TURNS
|
||||
export SKILLS_DIR
|
||||
export SYSTEM_PROMPT_FILE
|
||||
}
|
||||
|
||||
# Serve HTTP API
|
||||
serve_api() {
|
||||
echo "Starting Claude HTTP API on port $CLAUDE_PORT..."
|
||||
echo "Model: $CLAUDE_MODEL"
|
||||
echo "Max turns: $CLAUDE_MAX_TURNS"
|
||||
echo "Working directory: $SKILLS_DIR"
|
||||
|
||||
exec socat TCP-LISTEN:$CLAUDE_PORT,reuseaddr,fork EXEC:"/tmp/claude_handler.sh"
|
||||
}
|
||||
|
||||
create_handler
|
||||
serve_api
|
||||
Reference in New Issue
Block a user