mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
7.3 KiB
266 lines
7.3 KiB
#!/usr/bin/env bash
|
|
#
|
|
# headless_db_discovery.sh
|
|
#
|
|
# Multi-Agent Database Discovery using Claude Code
|
|
#
|
|
# This script runs Claude Code in non-interactive mode to perform
|
|
# comprehensive database discovery using 4 collaborating agents:
|
|
# STRUCTURAL, STATISTICAL, SEMANTIC, and QUERY.
|
|
#
|
|
# Usage:
|
|
# ./headless_db_discovery.sh [options]
|
|
#
|
|
# Options:
|
|
# -d, --database DB_NAME Database name to discover (default: discover from available)
|
|
# -s, --schema SCHEMA Schema name to analyze (default: all schemas)
|
|
# -o, --output FILE Output file for results (default: discovery_YYYYMMDD_HHMMSS.md)
|
|
# -m, --mcp-config JSON MCP server configuration (inline JSON)
|
|
# -f, --mcp-file FILE MCP server configuration file
|
|
# -t, --timeout SECONDS Timeout for discovery in seconds (default: 3600 = 1 hour)
|
|
# -v, --verbose Enable verbose output
|
|
# -h, --help Show this help message
|
|
#
|
|
# Examples:
|
|
# # Basic discovery (uses available MCP database connection)
|
|
# ./headless_db_discovery.sh
|
|
#
|
|
# # Discover specific database
|
|
# ./headless_db_discovery.sh -d mydb
|
|
#
|
|
# # With custom MCP server
|
|
# ./headless_db_discovery.sh -m '{"mcpServers": {"mydb": {"command": "...", "args": [...]}}}'
|
|
#
|
|
# # With output file
|
|
# ./headless_db_discovery.sh -o my_discovery_report.md
|
|
#
|
|
# Environment Variables:
|
|
# CLAUDE_PATH Path to claude executable (default: ~/.local/bin/claude)
|
|
#
|
|
|
|
set -e
|
|
|
|
# Default values
|
|
DATABASE_NAME=""
|
|
SCHEMA_NAME=""
|
|
OUTPUT_FILE=""
|
|
MCP_CONFIG=""
|
|
MCP_FILE=""
|
|
TIMEOUT=3600 # 1 hour default (multi-agent discovery takes longer)
|
|
VERBOSE=0
|
|
CLAUDE_CMD="${CLAUDE_PATH:-$HOME/.local/bin/claude}"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_verbose() {
|
|
if [ "$VERBOSE" -eq 1 ]; then
|
|
echo -e "${BLUE}[VERBOSE]${NC} $1"
|
|
fi
|
|
}
|
|
|
|
# Print usage
|
|
usage() {
|
|
grep '^#' "$0" | grep -v '!/bin/' | sed 's/^# //' | sed 's/^#//'
|
|
exit 0
|
|
}
|
|
|
|
# Parse command line arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-d|--database)
|
|
DATABASE_NAME="$2"
|
|
shift 2
|
|
;;
|
|
-s|--schema)
|
|
SCHEMA_NAME="$2"
|
|
shift 2
|
|
;;
|
|
-o|--output)
|
|
OUTPUT_FILE="$2"
|
|
shift 2
|
|
;;
|
|
-m|--mcp-config)
|
|
MCP_CONFIG="$2"
|
|
shift 2
|
|
;;
|
|
-f|--mcp-file)
|
|
MCP_FILE="$2"
|
|
shift 2
|
|
;;
|
|
-t|--timeout)
|
|
TIMEOUT="$2"
|
|
shift 2
|
|
;;
|
|
-v|--verbose)
|
|
VERBOSE=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
*)
|
|
log_error "Unknown option: $1"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validate Claude Code is available
|
|
if [ ! -f "$CLAUDE_CMD" ]; then
|
|
log_error "Claude Code not found at: $CLAUDE_CMD"
|
|
log_error "Set CLAUDE_PATH environment variable or ensure claude is in ~/.local/bin/"
|
|
exit 1
|
|
fi
|
|
|
|
# Set default output file if not specified
|
|
if [ -z "$OUTPUT_FILE" ]; then
|
|
OUTPUT_FILE="discovery_$(date +%Y%m%d_%H%M%S).md"
|
|
fi
|
|
|
|
# Get the directory where this script is located
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROMPT_FILE="$SCRIPT_DIR/prompts/multi_agent_discovery_prompt.md"
|
|
|
|
# Validate prompt file exists
|
|
if [ ! -f "$PROMPT_FILE" ]; then
|
|
log_error "Multi-agent discovery prompt not found at: $PROMPT_FILE"
|
|
log_error "Ensure the prompts/ directory exists with multi_agent_discovery_prompt.md"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Starting Multi-Agent Database Discovery"
|
|
log_info "Output will be saved to: $OUTPUT_FILE"
|
|
log_verbose "Using discovery prompt: $PROMPT_FILE"
|
|
|
|
# Read the base prompt
|
|
DISCOVERY_PROMPT="$(cat "$PROMPT_FILE")"
|
|
|
|
# Add database-specific context if provided
|
|
if [ -n "$DATABASE_NAME" ]; then
|
|
DISCOVERY_PROMPT="$DISCOVERY_PROMPT
|
|
|
|
**Target Database:** $DATABASE_NAME"
|
|
|
|
if [ -n "$SCHEMA_NAME" ]; then
|
|
DISCOVERY_PROMPT="$DISCOVERY_PROMPT
|
|
**Target Schema:** $SCHEMA_NAME"
|
|
fi
|
|
|
|
log_verbose "Target database: $DATABASE_NAME"
|
|
[ -n "$SCHEMA_NAME" ] && log_verbose "Target schema: $SCHEMA_NAME"
|
|
fi
|
|
|
|
# Build MCP args
|
|
MCP_ARGS=""
|
|
if [ -n "$MCP_CONFIG" ]; then
|
|
MCP_ARGS="--mcp-config $MCP_CONFIG"
|
|
log_verbose "Using inline MCP configuration"
|
|
elif [ -n "$MCP_FILE" ]; then
|
|
if [ -f "$MCP_FILE" ]; then
|
|
MCP_ARGS="--mcp-config $MCP_FILE"
|
|
log_verbose "Using MCP configuration from: $MCP_FILE"
|
|
else
|
|
log_error "MCP configuration file not found: $MCP_FILE"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Log the command being executed
|
|
log_info "Running Claude Code in headless mode with 6-agent discovery..."
|
|
log_verbose "Timeout: ${TIMEOUT}s"
|
|
|
|
# Build Claude command
|
|
CLAUDE_ARGS=(
|
|
--print
|
|
--no-session-persistence
|
|
--permission-mode bypassPermissions
|
|
)
|
|
|
|
# Add MCP configuration if available
|
|
if [ -n "$MCP_ARGS" ]; then
|
|
CLAUDE_ARGS+=($MCP_ARGS)
|
|
fi
|
|
|
|
# Execute Claude Code in headless mode
|
|
log_verbose "Executing: $CLAUDE_CMD ${CLAUDE_ARGS[*]}"
|
|
|
|
# Run the discovery and capture output
|
|
if timeout "${TIMEOUT}s" $CLAUDE_CMD "${CLAUDE_ARGS[@]}" <<< "$DISCOVERY_PROMPT" > "$OUTPUT_FILE" 2>&1; then
|
|
log_success "Discovery completed successfully!"
|
|
log_info "Report saved to: $OUTPUT_FILE"
|
|
|
|
# Print summary statistics
|
|
if [ -f "$OUTPUT_FILE" ]; then
|
|
lines=$(wc -l < "$OUTPUT_FILE")
|
|
words=$(wc -w < "$OUTPUT_FILE")
|
|
log_info "Report size: $lines lines, $words words"
|
|
|
|
# Check if file is empty (no output)
|
|
if [ "$lines" -eq 0 ]; then
|
|
log_warn "Output file is empty - discovery may have failed silently"
|
|
log_info "Try running with --verbose to see more details"
|
|
fi
|
|
|
|
# Try to extract key info if report contains markdown headers
|
|
if grep -q "^# " "$OUTPUT_FILE"; then
|
|
log_info "Report sections:"
|
|
grep "^# " "$OUTPUT_FILE" | head -10 | while read -r section; do
|
|
echo " - $section"
|
|
done
|
|
fi
|
|
fi
|
|
else
|
|
exit_code=$?
|
|
|
|
# Exit code 124 means timeout command killed the process
|
|
if [ "$exit_code" -eq 124 ]; then
|
|
log_error "Discovery timed out after ${TIMEOUT} seconds"
|
|
log_error "The multi-agent discovery process can take a long time for complex databases"
|
|
log_info "Try increasing timeout with: --timeout $((TIMEOUT * 2))"
|
|
log_info "Example: $0 --timeout $((TIMEOUT * 2))"
|
|
else
|
|
log_error "Discovery failed with exit code: $exit_code"
|
|
log_info "Check $OUTPUT_FILE for error details"
|
|
fi
|
|
|
|
# Show last few lines of output if it exists
|
|
if [ -f "$OUTPUT_FILE" ]; then
|
|
file_size=$(wc -c < "$OUTPUT_FILE")
|
|
if [ "$file_size" -gt 0 ]; then
|
|
log_verbose "Last 30 lines of output:"
|
|
tail -30 "$OUTPUT_FILE" | sed 's/^/ /'
|
|
else
|
|
log_warn "Output file is empty (0 bytes)"
|
|
log_info "This usually means Claude Code failed to start or produced no output"
|
|
log_info "Check that Claude Code is installed: $CLAUDE_CMD --version"
|
|
log_info "Or try with --verbose for more debugging information"
|
|
fi
|
|
fi
|
|
|
|
exit $exit_code
|
|
fi
|
|
|
|
log_success "Done!"
|