Files
2025-11-30 09:06:38 +08:00

120 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Configuration
CONTEXT_DIR="$(dirname "$0")/../context"
LOG_FILE="$CONTEXT_DIR/edit-log.txt"
LOCK_FILE="$CONTEXT_DIR/.edit-log.lock"
MAX_LOG_LINES=1000
LOCK_TIMEOUT=5
# Create context dir and log if doesn't exist
mkdir -p "$CONTEXT_DIR"
touch "$LOG_FILE"
# Acquire lock with timeout
acquire_lock() {
local count=0
while [ $count -lt $LOCK_TIMEOUT ]; do
if mkdir "$LOCK_FILE" 2>/dev/null; then
return 0
fi
sleep 0.2
count=$((count + 1))
done
# Log but don't fail - non-blocking requirement
echo "Warning: Could not acquire lock" >&2
return 1
}
# Release lock
release_lock() {
rmdir "$LOCK_FILE" 2>/dev/null || true
}
# Clean up lock on exit
trap release_lock EXIT
# Function to log edit
log_edit() {
local file_path="$1"
local tool_name="$2"
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
local repo=$(find_repo "$file_path")
if acquire_lock; then
echo "$timestamp | $repo | $tool_name | $file_path" >> "$LOG_FILE"
release_lock
fi
}
# Function to find repo root
find_repo() {
local file_path="$1"
if [ -z "$file_path" ] || [ "$file_path" = "null" ]; then
echo "unknown"
return
fi
local dir
dir=$(dirname "$file_path" 2>/dev/null || echo "/")
while [ "$dir" != "/" ] && [ -n "$dir" ]; do
if [ -d "$dir/.git" ]; then
basename "$dir"
return
fi
dir=$(dirname "$dir" 2>/dev/null || echo "/")
done
echo "unknown"
}
# Read tool use event from stdin (with timeout to prevent hanging)
if ! read -t 2 -r tool_use_json; then
echo '{}'
exit 0
fi
# Validate JSON to prevent injection
if ! echo "$tool_use_json" | jq empty 2>/dev/null; then
echo '{}'
exit 0
fi
# Extract tool name and file path from tool use
tool_name=$(echo "$tool_use_json" | jq -r '.tool.name // .tool_name // "unknown"' 2>/dev/null || echo "unknown")
file_path=""
case "$tool_name" in
"Edit"|"Write")
file_path=$(echo "$tool_use_json" | jq -r '.tool.input.file_path // .tool_input.file_path // "null"' 2>/dev/null || echo "null")
;;
"MultiEdit")
# MultiEdit has multiple files - log each
echo "$tool_use_json" | jq -r '.tool.input.edits[]?.file_path // .tool_input.edits[]?.file_path // empty' 2>/dev/null | while read -r path; do
if [ -n "$path" ] && [ "$path" != "null" ]; then
log_edit "$path" "$tool_name"
fi
done
echo '{}'
exit 0
;;
esac
# Log single edit
if [ -n "$file_path" ] && [ "$file_path" != "null" ]; then
log_edit "$file_path" "$tool_name"
fi
# Rotate log if too large (with lock)
if acquire_lock; then
line_count=$(wc -l < "$LOG_FILE" 2>/dev/null || echo "0")
if [ "$line_count" -gt "$MAX_LOG_LINES" ]; then
tail -n "$MAX_LOG_LINES" "$LOG_FILE" > "$LOG_FILE.tmp"
mv "$LOG_FILE.tmp" "$LOG_FILE"
fi
release_lock
fi
# Return success (non-blocking)
echo '{}'