forked from cyrusagents/cyrus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcollect-transcripts.sh
More file actions
executable file
·111 lines (89 loc) · 3.29 KB
/
collect-transcripts.sh
File metadata and controls
executable file
·111 lines (89 loc) · 3.29 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
#!/bin/bash
set -e
LOGS_SRC="$HOME/.cyrus/logs"
LOGS_DST="$(dirname "$0")/logs"
mkdir -p "$LOGS_DST/transcripts"
for dir in "$LOGS_SRC"/*/; do
name=$(basename "$dir")
jsonl_files=$(ls -tr "$dir"session*.jsonl 2>/dev/null | grep -v 'session-pending')
if [ -z "$jsonl_files" ]; then
echo "Skipping $name (no jsonl files)"
continue
fi
echo "Converting $name..."
merged="/tmp/cyrus-transcript-${name}.jsonl"
# Convert Cyrus SDK JSONL format to native Claude Code JSONL format
python3 -c "
import json, uuid, sys, glob
files = sys.argv[1:]
session_id = None
session_num = 0
for fpath in files:
with open(fpath) as f:
for line in f:
line = line.strip()
if not line:
continue
try:
d = json.loads(line)
except json.JSONDecodeError:
continue
msg_type = d.get('type')
ts = d.get('timestamp')
if msg_type == 'session-metadata':
session_id = d.get('sessionId', str(uuid.uuid4()))
session_num += 1
workspace = d.get('workspaceName', 'unknown')
# Inject a synthetic user prompt so the transcript tool sees a conversation
print(json.dumps({
'type': 'user',
'message': {
'role': 'user',
'content': f'[Cyrus session {session_num}: {workspace}] (sessionId: {session_id})'
},
'timestamp': ts or '',
'uuid': str(uuid.uuid4()),
'sessionId': session_id,
}))
continue
if msg_type != 'sdk-message':
continue
inner = d.get('message', {})
inner_type = inner.get('type')
if inner_type == 'system':
continue
if inner_type == 'result':
tool_result = inner.get('tool_result')
if tool_result:
print(json.dumps({
'type': 'user',
'message': {'role': 'user', 'content': tool_result.get('content', '')},
'timestamp': ts or '',
'uuid': inner.get('uuid', str(uuid.uuid4())),
'sessionId': session_id or inner.get('session_id', ''),
'toolUseResult': tool_result,
}))
continue
if inner_type not in ('assistant', 'user'):
continue
print(json.dumps({
'type': inner_type,
'message': inner.get('message', {}),
'timestamp': ts or '',
'uuid': inner.get('uuid', str(uuid.uuid4())),
'sessionId': session_id or inner.get('session_id', ''),
}))
" $jsonl_files > "$merged"
count=$(wc -l < "$merged")
if [ "$count" -eq 0 ]; then
echo " Skipping $name (no convertible messages)"
rm -f "$merged"
continue
fi
echo " $count messages"
uvx claude-code-transcripts json -o "$LOGS_DST/transcripts/$name" "$merged" 2>&1 | grep -v '^$'
rm -f "$merged"
echo " -> $LOGS_DST/transcripts/$name/index.html"
done
echo ""
echo "Done."