From 942f07612e545deb9d58c41c1b23a8708a39a08e Mon Sep 17 00:00:00 2001 From: Brianna Major Date: Mon, 2 Feb 2026 12:29:01 -0500 Subject: [PATCH 1/5] Use 1-indexed step display in UI Previously there was a mix of 1- and 0-indexed values displayed. --- .../core/static/mixtape/core/insights/replay.js | 13 ++++++++++++- .../templates/core/insights/replay_controls.html | 15 +++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/mixtape/core/static/mixtape/core/insights/replay.js b/mixtape/core/static/mixtape/core/insights/replay.js index 115956a..dce41b2 100644 --- a/mixtape/core/static/mixtape/core/insights/replay.js +++ b/mixtape/core/static/mixtape/core/insights/replay.js @@ -1,7 +1,14 @@ document.addEventListener('alpine:init', () => { Alpine.data('replay', () => ({ playing: false, + stepInput: 1, maxSteps: Alpine.store('insights').parsedData.max_steps - 1, + init() { + this.stepInput = this.$store.insights.currentStep + 1; + this.$watch('$store.insights.currentStep', (val) => { + this.stepInput = val + 1; + }); + }, stepForward() { if (!this.playing) { return; @@ -14,8 +21,12 @@ document.addEventListener('alpine:init', () => { }, delay); } else { this.playing = false; - this.$store.insights.currentStep = 0; } }, + jumpToStep() { + const val = Math.max(1, Math.min(this.maxSteps + 1, this.stepInput || 1)); + this.stepInput = val; + this.$store.insights.currentStep = val - 1; + }, })); }); diff --git a/mixtape/core/templates/core/insights/replay_controls.html b/mixtape/core/templates/core/insights/replay_controls.html index c41d37f..449defe 100644 --- a/mixtape/core/templates/core/insights/replay_controls.html +++ b/mixtape/core/templates/core/insights/replay_controls.html @@ -3,6 +3,7 @@ class="btn btn-ghost btn-sm" :disabled="$store.insights.currentStep === 0" @click="$store.insights.currentStep = 0" + title="Go to first step" > @@ -10,12 +11,14 @@ class="btn btn-ghost btn-sm" :disabled="$store.insights.currentStep === 0" @click="$store.insights.currentStep--" + title="Previous step" > @@ -31,6 +35,7 @@ class="btn btn-ghost btn-sm" :disabled="$store.insights.currentStep === maxSteps" @click="$store.insights.currentStep = maxSteps" + title="Go to last step" > @@ -39,10 +44,12 @@ x-cloak type="number" class="input input-sm validator w-16 text-center" - min="0" - :max="maxSteps" - x-model.number="$store.insights.currentStep" + min="1" + :max="maxSteps + 1" + x-model.number="stepInput" + @keydown.enter="jumpToStep()" + @blur="jumpToStep()" /> - / + / From f89de2de619a1548415f8525d401208e3b0c89dd Mon Sep 17 00:00:00 2001 From: Brianna Major Date: Mon, 2 Feb 2026 12:33:42 -0500 Subject: [PATCH 2/5] Fix multi-episode timeline toggling --- .../core/insights/clusteringTimeline.js | 3 +- .../mixtape/core/insights/insightsStore.js | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/mixtape/core/static/mixtape/core/insights/clusteringTimeline.js b/mixtape/core/static/mixtape/core/insights/clusteringTimeline.js index 4a926b3..761c7a1 100644 --- a/mixtape/core/static/mixtape/core/insights/clusteringTimeline.js +++ b/mixtape/core/static/mixtape/core/insights/clusteringTimeline.js @@ -59,7 +59,6 @@ document.addEventListener('alpine:init', () => { const step = this.$store.insights.currentStep; const xLine = [step, step]; const yLine = [yMin - 0.5, yMax + 0.5]; - // Use restyle: arguments must be arrays-of-arrays per selected trace Plotly.restyle(this.$el, { x: [xLine], y: [yLine] }, [1]); } }); @@ -99,7 +98,7 @@ document.addEventListener('alpine:init', () => { : 1; this.data = [ { - agentStepClusters: agentStepClusters, + z: agentStepClusters, type: 'heatmap', showscale: false, colorscale: 'YlGnBu', diff --git a/mixtape/core/static/mixtape/core/insights/insightsStore.js b/mixtape/core/static/mixtape/core/insights/insightsStore.js index 01cb858..9e136ce 100644 --- a/mixtape/core/static/mixtape/core/insights/insightsStore.js +++ b/mixtape/core/static/mixtape/core/insights/insightsStore.js @@ -21,6 +21,43 @@ document.addEventListener('alpine:init', () => { // Runtime values currentStep: 0, + // Get active timeline key steps based on global/episode mode + getActiveTimelineKeySteps() { + const settings = Alpine.store('settings'); + if (!settings) return []; + const useGlobal = settings.useGlobalTimeline; + const epIdx = settings.timelineEpisodeIdx; + + if (useGlobal && Array.isArray(this.timelineKeySteps)) { + // Global mode: merge all episodes' key steps, sort by reward, take top 40 + const allSteps = []; + this.timelineKeySteps.forEach((episodeSteps, episodeIdx) => { + if (Array.isArray(episodeSteps)) { + episodeSteps.forEach(step => { + allSteps.push({ + ...step, + episodeIdx: episodeIdx, + episodeId: this.episodeIds?.[episodeIdx] || episodeIdx, + }); + }); + } + }); + // Sort by total_rewards descending, take top 40, then sort by step number + const topSteps = allSteps + .sort((a, b) => b.total_rewards - a.total_rewards) + .slice(0, 40) + .sort((a, b) => { + // Sort by episode first, then by step number within episode + if (a.episodeIdx !== b.episodeIdx) return a.episodeIdx - b.episodeIdx; + return a.number - b.number; + }); + return topSteps; + } else { + // Episode mode: return selected episode's key steps + return this.timelineKeySteps?.[epIdx] || []; + } + }, + init() { // Parse JSON data this.parsedData = JSON.parse( From 9423e1581ae6d4f7d1d1aa48ff49b5cc4a53f318 Mon Sep 17 00:00:00 2001 From: Brianna Major Date: Mon, 2 Feb 2026 12:35:32 -0500 Subject: [PATCH 3/5] Fix action data for single vs multi-episode --- mixtape/core/views.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mixtape/core/views.py b/mixtape/core/views.py index 43432ee..824b98e 100644 --- a/mixtape/core/views.py +++ b/mixtape/core/views.py @@ -302,9 +302,15 @@ def insights(request: HttpRequest) -> HttpResponse: for episode_pk in episode_pks: insight_results = _episode_insights(episode_pk, group_by_episode) all_episode_details.append(insight_results['episode_details']) - all_action_v_reward[f'Episode {episode_pk}'] = insight_results['action_v_reward'] + if group_by_episode: + # Multi-episode: wrap each episode's aggregated data under Episode key + all_action_v_reward[f'Episode {episode_pk}'] = insight_results['action_v_reward'] + all_action_v_frequency[f'Episode {episode_pk}'] = insight_results['action_v_frequency'] + else: + # Single episode: data is already keyed by agent, use directly + all_action_v_reward = insight_results['action_v_reward'] + all_action_v_frequency = insight_results['action_v_frequency'] all_reward_histogram.append(insight_results['reward_histogram']) - all_action_v_frequency[f'Episode {episode_pk}'] = insight_results['action_v_frequency'] all_rewards_over_time.append(insight_results['rewards_over_time']) all_decomposed_rewards.append(insight_results['decomposed_rewards']) all_step_data.append(insight_results['step_data']) From b912e598a96c856d7ea26dd38ec61dab10663371 Mon Sep 17 00:00:00 2001 From: Brianna Major Date: Mon, 2 Feb 2026 12:38:15 -0500 Subject: [PATCH 4/5] Add feedback to indicate end of episode --- .../insights/partials/_tabs_overview.html | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/mixtape/core/templates/core/insights/partials/_tabs_overview.html b/mixtape/core/templates/core/insights/partials/_tabs_overview.html index 73b6591..626ed3a 100644 --- a/mixtape/core/templates/core/insights/partials/_tabs_overview.html +++ b/mixtape/core/templates/core/insights/partials/_tabs_overview.html @@ -58,11 +58,19 @@ - + - + @@ -224,11 +232,16 @@

Actions

{% include "core/insights/timeline.html" %}
-
-
+
+
{% include "core/insights/episode_info.html" %}
-
+
{% include "core/insights/media_viewer.html" %}
From b46e681572d141858a01830113d70e84cf170e73 Mon Sep 17 00:00:00 2001 From: Brianna Major Date: Mon, 2 Feb 2026 12:38:48 -0500 Subject: [PATCH 5/5] Minor UI improvements and cleanup --- .../templates/core/insights/episode_info.html | 100 +++++++++++------- .../templates/core/insights/media_viewer.html | 4 +- .../templates/core/insights/timeline.html | 12 ++- .../shared/partials/_side_panel_overview.html | 2 +- 4 files changed, 73 insertions(+), 45 deletions(-) diff --git a/mixtape/core/templates/core/insights/episode_info.html b/mixtape/core/templates/core/insights/episode_info.html index 8bac15c..2f40786 100644 --- a/mixtape/core/templates/core/insights/episode_info.html +++ b/mixtape/core/templates/core/insights/episode_info.html @@ -1,41 +1,65 @@ -
-
- - - - - - - - - - - -
Agents