flake-update-20260505
  1#!/usr/bin/env bash
  2# Helper for pir-fork: list and preview pi sessions.
  3# Called by the pir-fork zsh function and by fzf --preview/--bind reload.
  4#
  5# Usage:
  6#   _pi-session-helper list [--all] [--days N] [--cwd DIR]
  7#   _pi-session-helper preview UUID
  8set -euo pipefail
  9
 10SESSION_DIR="${HOME}/.pi/agent/sessions/"
 11
 12cmd_list() {
 13  local show_all="false"
 14  local days=""
 15  local filter_cwd=""
 16
 17  while [[ $# -gt 0 ]]; do
 18    case "$1" in
 19      --all)       show_all="true"; shift ;;
 20      --days)      days="$2"; shift 2 ;;
 21      --cwd)       filter_cwd="$2"; shift 2 ;;
 22      *)           shift ;;
 23    esac
 24  done
 25
 26  # Compute cutoff date if --days is set
 27  local date_cutoff=""
 28  if [[ -n "$days" ]]; then
 29    date_cutoff=$(date -d "-${days} days" +%Y-%m-%d 2>/dev/null || date -v-${days}d +%Y-%m-%d 2>/dev/null || echo "")
 30  fi
 31
 32  find "$SESSION_DIR" -name '*.jsonl' -type f -print0 \
 33    | xargs -0 -P8 -n100 gawk \
 34        -v home="$HOME" \
 35        -v show_all="$show_all" \
 36        -v filter_cwd="$filter_cwd" \
 37        -v date_cutoff="$date_cutoff" '
 38    FNR==1 {
 39      id = ""; ts = ""; cwd = ""; msg = ""; found_user = 0
 40      if (match($0, /"id":"([^"]+)"/, m)) id = m[1]
 41      if (match($0, /"timestamp":"([^"]+)"/, m)) ts = m[1]
 42      if (match($0, /"cwd":"([^"]+)"/, m)) cwd = m[1]
 43      if (id == "") nextfile
 44      if (show_all != "true" && filter_cwd != "" && index(cwd, filter_cwd) != 1) {
 45        id = ""; nextfile
 46      }
 47      next
 48    }
 49    !found_user && /"role":"user"/ {
 50      found_user = 1
 51      if (match($0, /"text":"([^"]{1,80})/, m)) {
 52        msg = m[1]
 53        gsub(/\\n/, " ", msg)
 54      }
 55      nextfile
 56    }
 57    ENDFILE {
 58      if (id != "" && ts != "") {
 59        date_part = ts
 60        sub(/T.*/, "", date_part)
 61        if (date_part ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/) {
 62          if (date_cutoff == "" || date_part >= date_cutoff) {
 63            short_cwd = cwd
 64            gsub(home, "~", short_cwd)
 65            printf "%s\t%s\t%s\t%s\n", date_part, short_cwd, msg, id
 66          }
 67        }
 68      }
 69    }
 70  ' \
 71    | grep -P '^\d{4}-\d{2}-\d{2}\t' \
 72    | sort -t$'\t' -rk1,1
 73}
 74
 75cmd_preview() {
 76  local uuid="$1"
 77  local f
 78  f=$(find "$SESSION_DIR" -name "*_${uuid}.jsonl" -type f | head -1)
 79
 80  [[ -z "$f" ]] && { echo "Session file not found"; return 1; }
 81
 82  # Session metadata from header
 83  local header
 84  header=$(head -1 "$f")
 85  local ts cwd
 86  ts=$(echo "$header" | grep -oP '"timestamp":"\K[^"]+' || true)
 87  cwd=$(echo "$header" | grep -oP '"cwd":"\K[^"]+' || true)
 88  cwd="${cwd/$HOME/\~}"
 89
 90  # Count messages
 91  local msg_count
 92  msg_count=$(grep -c '"type":"message"' "$f" 2>/dev/null || echo 0)
 93
 94  # Model info
 95  local model
 96  model=$(grep -oP '"modelId":"\K[^"]+' "$f" 2>/dev/null | tail -1 || true)
 97
 98  # Print metadata header
 99  echo "📅 ${ts}"
100  echo "📁 ${cwd}"
101  echo "💬 ${msg_count} messages"
102  [[ -n "$model" ]] && echo "🤖 ${model}"
103  echo "────────────────────────────────"
104
105  # Show conversation exchanges
106  grep '"type":"message"' "$f" 2>/dev/null \
107    | head -30 \
108    | jq -r '
109      (.message.role // "?") as $role |
110      (
111        if .message.content | type == "array" then
112          [.message.content[] | select(.type == "text") | .text] | join(" ")
113        elif .message.content | type == "string" then
114          .message.content
115        else
116          ""
117        end
118      ) as $text |
119      if $role == "user" then
120        "▶ " + ($text | gsub("\n"; " ") | .[0:200])
121      elif $role == "assistant" then
122        "  " + ($text | gsub("\n"; " ") | .[0:200])
123      else
124        empty
125      end
126    ' 2>/dev/null
127}
128
129case "${1:-}" in
130  list)    shift; cmd_list "$@" ;;
131  preview) shift; cmd_preview "$@" ;;
132  *)       echo "Usage: _pi-session-helper {list|preview} [args...]" >&2; exit 1 ;;
133esac