-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathai-commit-msg
More file actions
executable file
·180 lines (149 loc) · 5.54 KB
/
ai-commit-msg
File metadata and controls
executable file
·180 lines (149 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env bash
# Exit if the `SKIP_AI_COMMIT_MSG_HOOK` environment variable is set
if [ -n "$GITAI_SKIP_AI_COMMIT_MSG_HOOK" ]; then
exit 0
fi
# ANSI color codes for styling the output
RED='\033[0;31m' # Sets text to red
GREEN='\033[0;32m' # Sets text to green
YELLOW='\033[0;33m' # Sets text to yellow
BLUE='\033[0;34m' # Sets text to blue
NC='\033[0m' # Resets the text color to default, no color
DEFAULT_PROMPT_FILE=$HOME/.config/gitai/prompts/ai-commit-msg-prompt.txt
# Function to display help message
show_help() {
cat <<EOF
Usage: $(basename "$0") [options]
Automatically generates a commit message for staged changes using an LLM.
This script is typically used as a 'prepare-commit-msg' Git hook.
Options:
-h, --help Display this help message and exit.
Environment Variables:
GITAI_SKIP_AI_COMMIT_MSG_HOOK If set to a non-empty value, the script will exit without generating a message.
GITAI_MODEL Specifies the LLM model to use (e.g., 'gpt-4o'). Defaults to the model set as default in the 'llm' tool.
GITAI_COMMIT_MSG_PROMPT Path to a custom prompt file. Defaults to '$DEFAULT_PROMPT_FILE'.
GITAI_LANG The language for the generated commit message. Defaults to 'English'.
EOF
}
# Function to display a spinning animation during the LLM processing
spin_animation() {
local msg="$1"
# Only show animation if output is going to a terminal
if ! [ -t 1 ]; then
echo "$1..." # Just show the message without animation
return
fi
# Array of spinner characters for the animation
local spinner=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
# Infinite loop to keep the animation running
while true; do
for i in "${spinner[@]}"; do
tput civis # Hide the cursor to enhance the animation appearance
tput el1 # Clear the line from the cursor to the beginning to display the spinner
printf "\r${YELLOW}%s${NC} %s..." "$i" "$msg" # Print the spinner and message
sleep 0.1 # Delay to control the speed of the animation
tput cub $((${#msg} + 5)) # Move the cursor back to reset the spinner position
done
done
}
kill_spin() {
if [ -n "$SPIN_PID" ]; then
kill $SPIN_PID
wait $SPIN_PID 2>/dev/null # Wait for the process to terminate and suppress error messages
SPIN_PID=
printf "\n"
fi
}
# Function to handle interrupts
cleanup() {
echo -e "\n${RED}Script interrupted. Cleaning up...${NC}"
kill_spin
tput cnorm # Show the cursor
exit 1
}
init_config() {
if [ ! -f "$DEFAULT_PROMPT_FILE" ]; then
brew_prompt=$(brew --prefix)/share/gitai/prompts/ai-commit-msg-prompt.txt
if [ ! -f "$brew_prompt" ]; then
echo "Can't find a default configuration file. Please create one at $DEFAULT_PROMPT_FILE" >&2
exit 1
fi
dir=$(dirname "$DEFAULT_PROMPT_FILE")
mkdir -p "$dir"
cp "$brew_prompt" "$DEFAULT_PROMPT_FILE"
fi
}
init_config
trap cleanup SIGINT
# Parse command-line arguments for help flag
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
show_help
exit 0
fi
# Check if the commit is a merge commit based on the presence of a second argument
if [ -n "$2" ]; then
exit 0 # Exit script if it's a merge commit, no custom message needed
fi
# Check if the `llm` command is installed
if ! command -v llm &>/dev/null; then
echo -e "${RED}Error: 'llm' command is not installed. Please install it and try again.${NC}"
exit 1
fi
# The LLM command will use the model by the environment `MODEL`
MODEL=${GITAI_MODEL}
if [ -z "$MODEL" ]; then
MODEL=$(llm models default)
fi
export LLM_MODEL="$MODEL"
PROMPT_FILE=${GITAI_COMMIT_MSG_PROMPT:-$DEFAULT_PROMPT_FILE}
LANGUAGE=${GITAI_LANG:-English}
if [ ! -f "$PROMPT_FILE" ]; then
echo -e "${RED}Error: Prompt file not found: $PROMPT_FILE${NC}" >&2
exit 1
fi
PROMPT_CONTENT="$(cat "$PROMPT_FILE")"
PROMPT=$(
cat <<EOF
All non-code text responses must be written in the $LANGUAGE language indicated.
$PROMPT_CONTENT
EOF
)
diff=$(git diff --cached)
if [ -z "$diff" ]; then
exit 0
fi
# Start the spinning animation in the background
spin_animation "Generating LLM commit message using $MODEL" &
SPIN_PID=$!
# Generate the commit message using `git diff` piped into `llm` command
# The LLM command takes a system prompt from a file as input
if ! commit_msg=$(echo "$diff" | llm -s "$PROMPT" 2>&1); then
# Stop the spinning animation by killing its process
kill_spin
# Finalizing output
tput cnorm # Show the cursor again
printf "\n" # Move the cursor to the next line
printf "${RED}Error: 'llm' command failed to generate the commit message:\n${commit_msg}${NC}\n\nManually set the commit message"
exit 1
fi
# Stop the spinning animation by killing its process
kill_spin
# Display the generated commit message with color-coded headings
# echo -e "${BLUE}=== Generated Commit Message ===${NC}"
# echo -e "${GREEN}$commit_msg${NC}"
# echo -e "${BLUE}=================================${NC}"
# echo
# Write the generated commit message to the specified file (usually the commit message file in .git)
TMP_FILE=$(mktemp)
if [ -z "$TMP_FILE" ]; then
exit 1
fi
trap 'rm -f -- "$TMP_FILE"' EXIT
if ! {
echo "$commit_msg"
cat -- "$1"
} >"$TMP_FILE"; then
echo "Error: Failed to stage new commit message, preserving original." >&2
exit 1
fi
mv -- "$TMP_FILE" "$1"