Skip to content

Commit b30164c

Browse files
authored
Merge pull request #9 from redhat-developer/feat/agentsview-fullsend-integration
feat: AgentsView integration for fullsend runs
2 parents 089428a + 74bb532 commit b30164c

4 files changed

Lines changed: 184 additions & 0 deletions

File tree

agentsview/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/runs/

agentsview/Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.DEFAULT_GOAL := help
2+
3+
COMPOSE := $(if $(shell command -v podman 2>/dev/null),podman compose,docker compose)
4+
5+
.PHONY: fetch up down help
6+
7+
# Fetch fullsend agent runs from GitHub Actions into ./runs
8+
fetch:
9+
./scripts/fetch-fullsend-runs.sh
10+
11+
# Fetch runs + start AgentsView container (Podman preferred, Docker fallback)
12+
up: fetch
13+
$(COMPOSE) -f docker-compose.fullsend.yaml up -d
14+
@echo "AgentsView: http://$$(hostname).local:$${AGENTSVIEW_PORT:-8081}"
15+
16+
# Stop AgentsView container
17+
down:
18+
$(COMPOSE) -f docker-compose.fullsend.yaml down
19+
20+
help:
21+
@echo "AgentsView fullsend integration"
22+
@echo ""
23+
@echo " make fetch - Download fullsend runs from GitHub Actions"
24+
@echo " make up - Fetch + start AgentsView (http://localhost:8081)"
25+
@echo " make down - Stop AgentsView"
26+
@echo ""
27+
@echo "Environment variables:"
28+
@echo " AGENTSVIEW_PORT - Host port (default: 8081)"
29+
@echo " AGENTSVIEW_HOST - Public hostname for remote access (default: localhost)"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
services:
2+
agentsview:
3+
image: ghcr.io/kenn-io/agentsview:latest
4+
restart: unless-stopped
5+
ports:
6+
- "0.0.0.0:${AGENTSVIEW_PORT:-8081}:8080"
7+
environment:
8+
CLAUDE_PROJECTS_DIR: /agents/claude
9+
command:
10+
- "--host"
11+
- "0.0.0.0"
12+
- "--no-browser"
13+
- "--public-url"
14+
- "http://${AGENTSVIEW_HOST:-localhost}:${AGENTSVIEW_PORT:-8081}"
15+
volumes:
16+
- agentsview-fullsend-data:/data
17+
- ./runs:/agents/claude:ro
18+
19+
volumes:
20+
agentsview-fullsend-data:
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Download fullsend agent run transcripts from GitHub Actions and
5+
# organise them so AgentsView can ingest them as Claude sessions.
6+
#
7+
# Usage:
8+
# ./fetch-fullsend-runs.sh # default repos
9+
# ./fetch-fullsend-runs.sh org/repo1 org/repo2 # custom repos
10+
#
11+
# Prerequisites: gh (authenticated), jq
12+
#
13+
# Directory layout produced (matches AgentsView Claude discovery):
14+
# runs/<repo>_<agent>/<run-id>_issue-<N>_<transcript>.jsonl
15+
16+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
17+
RUNS_DIR="${RUNS_DIR:-${SCRIPT_DIR}/../runs}"
18+
19+
if [ $# -gt 0 ]; then
20+
REPOS=("$@")
21+
else
22+
REPOS=("redhat-developer/rhdh-agentic" "redhat-developer/rhdh-plugins")
23+
fi
24+
25+
for cmd in gh jq; do
26+
command -v "$cmd" >/dev/null 2>&1 || { echo "error: $cmd is required" >&2; exit 1; }
27+
done
28+
29+
mkdir -p "$RUNS_DIR"
30+
31+
echo "Fetching fullsend runs -> $RUNS_DIR"
32+
echo "Repos: ${REPOS[*]}"
33+
echo
34+
35+
total_fetched=0
36+
total_skipped=0
37+
38+
for repo in "${REPOS[@]}"; do
39+
repo_name=$(basename "$repo")
40+
echo "--- $repo ---"
41+
42+
# Fetch all artifacts with automatic pagination
43+
artifacts=$(gh api --paginate "repos/${repo}/actions/artifacts?per_page=100" \
44+
--jq '[.artifacts[] | select(.name | startswith("fullsend-")) | select(.expired == false) | {id:.id, name:.name, run_id:.workflow_run.id, created:.created_at}]' 2>/dev/null \
45+
| jq -s 'add // []') || {
46+
echo " [skip] could not list artifacts"
47+
continue
48+
}
49+
50+
count=$(echo "$artifacts" | jq 'length')
51+
echo " $count fullsend artifact(s)"
52+
53+
for i in $(seq 0 $((count - 1))); do
54+
art_name=$(echo "$artifacts" | jq -r ".[$i].name")
55+
run_id=$(echo "$artifacts" | jq -r ".[$i].run_id")
56+
created=$(echo "$artifacts" | jq -r ".[$i].created")
57+
agent_name=${art_name#fullsend-}
58+
59+
# Skip if we already have files for this run+agent
60+
project_dir="${repo_name}_${agent_name}"
61+
if compgen -G "${RUNS_DIR}/${project_dir}/${run_id}_*.jsonl" >/dev/null 2>&1; then
62+
total_skipped=$((total_skipped + 1))
63+
continue
64+
fi
65+
66+
# Get run metadata (title, conclusion, URL)
67+
run_meta=$(gh api "repos/${repo}/actions/runs/${run_id}" \
68+
--jq '{title:.display_title, conclusion:.conclusion, url:.html_url}' 2>/dev/null) || continue
69+
title=$(echo "$run_meta" | jq -r '.title')
70+
conclusion=$(echo "$run_meta" | jq -r '.conclusion')
71+
run_url=$(echo "$run_meta" | jq -r '.url')
72+
73+
echo " run $run_id | $art_name | $conclusion"
74+
75+
tmpdir=$(mktemp -d)
76+
77+
if ! gh run download "$run_id" --repo "$repo" --dir "$tmpdir" --name "$art_name" 2>/dev/null; then
78+
rm -rf "$tmpdir"
79+
echo " (download failed)"
80+
continue
81+
fi
82+
83+
# Extract issue number from artifact directory name: agent-<type>-<issue>-<hash>
84+
issue_num=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d -name 'agent-*' \
85+
| head -1 | xargs basename 2>/dev/null \
86+
| grep -oE 'agent-[a-z]+-([0-9]+)' | grep -oE '[0-9]+$' || true)
87+
[ -z "$issue_num" ] && issue_num="unknown"
88+
89+
dest_dir="${RUNS_DIR}/${project_dir}"
90+
91+
found=false
92+
while IFS= read -r -d '' jsonl; do
93+
found=true
94+
mkdir -p "$dest_dir"
95+
96+
dest_file="${dest_dir}/${run_id}_issue-${issue_num}_$(basename "$jsonl")"
97+
98+
# Prepend a context message so the session shows repo/issue/agent in AgentsView
99+
meta_line=$(jq -nc \
100+
--arg repo "$repo" \
101+
--arg issue "$issue_num" \
102+
--arg agent "$agent_name" \
103+
--arg conclusion "$conclusion" \
104+
--arg url "$run_url" \
105+
--arg ts "$created" \
106+
--arg cwd "/fullsend/${project_dir}" \
107+
'{
108+
type: "user",
109+
timestamp: $ts,
110+
message: {
111+
content: ("[Fullsend: \($agent)] \($repo)#\($issue) (\($conclusion))\n\($url)")
112+
},
113+
cwd: $cwd
114+
}')
115+
116+
{ echo "$meta_line"; cat "$jsonl"; } > "$dest_file"
117+
echo " -> ${project_dir}/$(basename "$dest_file")"
118+
total_fetched=$((total_fetched + 1))
119+
done < <(find "$tmpdir" -name '*.jsonl' -path '*/transcripts/*' -print0)
120+
121+
if [ "$found" = "false" ]; then
122+
echo " (no transcripts in artifact)"
123+
fi
124+
125+
rm -rf "$tmpdir"
126+
done
127+
128+
echo
129+
done
130+
131+
echo "Done: ${total_fetched} fetched, ${total_skipped} skipped"
132+
if [ "$total_fetched" -gt 0 ] || [ "$total_skipped" -gt 0 ]; then
133+
echo "Start viewer: make fullsend-up (or: podman compose -f docker-compose.fullsend.yaml up -d)"
134+
fi

0 commit comments

Comments
 (0)