diff --git a/skills/kugetsu/scripts/kugetsu-log.sh b/skills/kugetsu/scripts/kugetsu-log.sh index 0e9ee0f..ce34984 100755 --- a/skills/kugetsu/scripts/kugetsu-log.sh +++ b/skills/kugetsu/scripts/kugetsu-log.sh @@ -45,22 +45,61 @@ cmd_logs() { find "$LOGS_DIR" -type f -mtime +7 -delete 2>/dev/null - ls -lt "$LOGS_DIR" | head -$((count + 1)) | tail -$count | while read line; do - echo "$line" + local log_files=() + while IFS= read -r line; do + log_files+=("$line") + done < <(ls -lt "$LOGS_DIR" | head -$((count + 1)) | tail -$count | awk '{print $NF}') + + echo "=== Recent Logs ($count files) ===" + echo "" + printf "%-30s %8s %s\n" "FILE" "SIZE" "LAST MODIFIED" + echo "----------------------------------------------------------------" + + for log in "${log_files[@]}"; do + if [ -f "$LOGS_DIR/$log" ]; then + local size=$(stat -c %s "$LOGS_DIR/$log" 2>/dev/null || echo "0") + local mtime=$(stat -c %Y "$LOGS_DIR/$log" 2>/dev/null || echo "0") + local date_str=$(date -d "@$mtime" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "unknown") + printf "%-30s %8s %s\n" "$log" "$size" "$date_str" + fi done echo "" - echo "Recent log contents:" - echo "====================" + echo "Log Contents:" + echo "================================================================" - for log in $(ls -lt "$LOGS_DIR" | head -$((count + 1)) | tail -$count | awk '{print $NF}'); do + for log in "${log_files[@]}"; do if [ -f "$LOGS_DIR/$log" ]; then echo "" - echo "--- $log ---" + echo ">>> $log <<<" + echo "----------------------------------------------------------------" tail -20 "$LOGS_DIR/$log" | while read line; do line=$(strip_ansi_codes "$line") line=$(mask_sensitive_vars "$line") - echo " $line" + + if [[ "$line" =~ \[([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[^\]]*)\]\ ([a-z]+)\ (.+) ]]; then + local ts="${BASH_REMATCH[1]}" + local level="${BASH_REMATCH[2]}" + local msg="${BASH_REMATCH[3]}" + + local color="" + local level_str="" + case "$level" in + error) color="\033[0;31m"; level_str="[ERROR]" ;; + warn) color="\033[0;33m"; level_str="[WARN ]" ;; + info) color="\033[0;32m"; level_str="[INFO ]" ;; + debug) color="\033[0;36m"; level_str="[DEBUG]" ;; + *) color="\033[0;90m"; level_str="[$level]" ;; + esac + + if [ -t 1 ]; then + echo -e " \033[0;90m$ts\033[0m ${color}${level_str}\033[0m $msg" + else + echo " $ts ${level_str} $msg" + fi + else + echo " $line" + fi done fi done diff --git a/skills/kugetsu/scripts/kugetsu-session.sh b/skills/kugetsu/scripts/kugetsu-session.sh index b6ffaf5..5b52f96 100755 --- a/skills/kugetsu/scripts/kugetsu-session.sh +++ b/skills/kugetsu/scripts/kugetsu-session.sh @@ -559,53 +559,69 @@ cmd_list() { fi echo "" - echo "Issue sessions:" + + local issue_sessions=() if [ -d "$SESSIONS_DIR" ]; then for session_file in "$SESSIONS_DIR"/*.json; do if [ -f "$session_file" ]; then local filename=$(basename "$session_file") if [ "$filename" != "base.json" ] && [ "$filename" != "pm-agent.json" ]; then + local mtime=$(stat -c %Y "$session_file" 2>/dev/null || echo "0") local issue_ref=$(filename_to_issue_ref "$filename") local opencode_sid=$(python3 -c "import json; print(json.load(open('$session_file')).get('opencode_session_id', 'unknown'))" 2>/dev/null || echo "unknown") local state=$(python3 -c "import json; print(json.load(open('$session_file')).get('state', 'unknown'))" 2>/dev/null || echo "unknown") local worktree_path=$(python3 -c "import json; print(json.load(open('$session_file')).get('worktree_path', ''))" 2>/dev/null || echo "") - local worktree_status="" - if [ -n "$worktree_path" ]; then - if [ -d "$worktree_path" ]; then - worktree_status="(worktree exists)" - else - worktree_status="(worktree MISSING)" - fi - fi - echo " $filename" - echo " Issue: $issue_ref" - echo " Session: $opencode_sid" - echo " State: $state" - echo " $worktree_status" + issue_sessions+=("$mtime|$filename|$issue_ref|$opencode_sid|$state|$worktree_path") fi fi done fi + if [ ${#issue_sessions[@]} -gt 0 ]; then + printf "%-45s %-10s %-20s %s\n" "ISSUE_REF" "STATE" "LAST_UPDATED" "SESSION_ID" + echo "-------------------------------------------------------------------------------------------------------------" + + while IFS='|' read -r mtime filename issue_ref opencode_sid state worktree_path; do + local last_updated=$(date -d "@$mtime" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "unknown") + local worktree_status="" + if [ -n "$worktree_path" ] && [ ! -d "$worktree_path" ]; then + worktree_status=" [worktree MISSING]" + fi + printf "%-45s %-10s %-20s %s%s\n" "$issue_ref" "$state" "$last_updated" "$opencode_sid" "$worktree_status" + done < <(printf '%s\n' "${issue_sessions[@]}" | sort -t'|' -k1 -rn) + else + echo "No issue sessions found." + fi + + echo "" + + local orphaned_worktrees=() if [ -d "$WORKTREES_DIR" ]; then - echo "" - echo "Worktrees without sessions:" for worktree in $(find "$WORKTREES_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null); do local worktree_name=$(basename "$worktree") local has_session=false - for session_file in "$SESSIONS_DIR"/*.json; do - if [ -f "$session_file" ]; then - local wt_path=$(python3 -c "import json; print(json.load(open('$session_file')).get('worktree_path', ''))" 2>/dev/null || echo "") - if [ "$wt_path" = "$worktree" ]; then - has_session=true - break + if [ -d "$SESSIONS_DIR" ]; then + for session_file in "$SESSIONS_DIR"/*.json; do + if [ -f "$session_file" ]; then + local wt_path=$(python3 -c "import json; print(json.load(open('$session_file')).get('worktree_path', ''))" 2>/dev/null || echo "") + if [ "$wt_path" = "$worktree" ]; then + has_session=true + break + fi fi - fi - done - if [ "$has_session" = false ]; then - echo " $worktree_name (no session)" + done fi + if [ "$has_session" = false ]; then + orphaned_worktrees+=("$worktree_name") + fi + done + fi + + if [ ${#orphaned_worktrees[@]} -gt 0 ]; then + echo "Worktrees without sessions:" + for wt in "${orphaned_worktrees[@]}"; do + echo " $wt" done fi }