aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-ai/replay-states.sh
blob: 791ad47e1debbafad36ae13706d596f9170f93c0 (plain) (blame)
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
#!/bin/bash
# Replay state snapshots from a debug state JSONL file
# Usage: ./replay-states.sh <state-file.jsonl> [entry-number]
#   With no entry: renders all frames in sequence (press Enter to advance)
#   With entry number: renders just that frame

set -e
# cd "$(dirname "$0")"

STATE_FILE="${1:-}"
ENTRY_FILTER="${2:-}"

if [[ -z "$STATE_FILE" ]]; then
    echo "Usage: $0 <state-file.jsonl> [entry-number]"
    echo ""
    echo "Examples:"
    echo "  $0 /tmp/state.jsonl          # Interactive replay of all frames"
    echo "  $0 /tmp/state.jsonl 15       # Show just entry 15"
    exit 1
fi

if [[ ! -f "$STATE_FILE" ]]; then
    echo "Error: File not found: $STATE_FILE"
    exit 1
fi

# Build once
cargo build -p atuin --quiet

# Count entries
TOTAL=$(wc -l < "$STATE_FILE" | tr -d ' ')

if [[ -n "$ENTRY_FILTER" ]]; then
    # Show single entry
    LINE=$(sed -n "${ENTRY_FILTER}p" "$STATE_FILE")
    if [[ -z "$LINE" ]]; then
        echo "Error: Entry $ENTRY_FILTER not found (file has $TOTAL entries)"
        exit 1
    fi

    ENTRY=$(echo "$LINE" | jq -r '.entry')
    LABEL=$(echo "$LINE" | jq -r '.label')
    STATE=$(echo "$LINE" | jq -c '.state')

    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "[$ENTRY/$TOTAL] $LABEL"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "$STATE" | cargo run -p atuin --quiet -- ai debug-render -f ansi
else
    # Interactive replay
    echo "Replaying $TOTAL frames from $STATE_FILE"
    echo "Press Enter to advance, 'q' to quit, or number+Enter to jump"
    echo ""

    CURRENT=1
    while [[ $CURRENT -le $TOTAL ]]; do
        LINE=$(sed -n "${CURRENT}p" "$STATE_FILE")
        ENTRY=$(echo "$LINE" | jq -r '.entry')
        LABEL=$(echo "$LINE" | jq -r '.label')
        STATE=$(echo "$LINE" | jq -c '.state')

        clear
        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        echo "[$CURRENT/$TOTAL] $LABEL"
        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        echo "$STATE" | cargo run -p atuin --quiet -- ai debug-render -f ansi
        echo ""
        echo "[Enter: next] [p: prev] [number: jump] [s: show state JSON] [q: quit]"

        read -r INPUT
        case "$INPUT" in
            q|Q)
                break
                ;;
            p|P)
                if [[ $CURRENT -gt 1 ]]; then
                    CURRENT=$((CURRENT - 1))
                fi
                ;;
            s|S)
                echo ""
                echo "State JSON:"
                echo "$STATE" | jq .
                echo ""
                echo "Press Enter to continue..."
                read -r
                ;;
            ''|' ')
                CURRENT=$((CURRENT + 1))
                ;;
            *[0-9]*)
                if [[ "$INPUT" =~ ^[0-9]+$ ]] && [[ "$INPUT" -ge 1 ]] && [[ "$INPUT" -le $TOTAL ]]; then
                    CURRENT=$INPUT
                else
                    echo "Invalid entry number (1-$TOTAL)"
                    sleep 1
                fi
                ;;
        esac
    done
fi