Zayne Rea Sprague Claude Opus 4.6 commited on
Commit
45f09e7
·
1 Parent(s): 499ba81

feat: add Raw Prompt dropdown to arena transcript view

Browse files

Each turn bubble now has a collapsible "Raw Prompt" section showing
the reconstructed messages array (system + prior user/assistant turns)
that would have been sent to the API at that point in the conversation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

frontend/src/arena/components/TranscriptPanel.tsx CHANGED
@@ -102,7 +102,14 @@ export default function TranscriptPanel({ datasetName, repoName, data, dragHandl
102
  <SystemPromptBubble text={data.system_prompt} />
103
  )}
104
  {data.transcript.map((turn, i) => (
105
- <TurnBubble key={i} turn={turn} hasMultiplePlayers={data.opponent_model !== null} />
 
 
 
 
 
 
 
106
  ))}
107
  </div>
108
  </div>
@@ -134,8 +141,34 @@ function SystemPromptBubble({ text }: { text: string }) {
134
  }
135
 
136
 
137
- function TurnBubble({ turn, hasMultiplePlayers }: { turn: TranscriptTurn; hasMultiplePlayers: boolean }) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  const [thinkExpanded, setThinkExpanded] = useState(false);
 
139
  const playerColor = getPlayerColor(turn.player_id);
140
  const thinkSegments = highlightTrace(turn.think_text);
141
 
@@ -193,6 +226,22 @@ function TurnBubble({ turn, hasMultiplePlayers }: { turn: TranscriptTurn; hasMul
193
  </div>
194
  </div>
195
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  </div>
197
  );
198
  }
 
102
  <SystemPromptBubble text={data.system_prompt} />
103
  )}
104
  {data.transcript.map((turn, i) => (
105
+ <TurnBubble
106
+ key={i}
107
+ turn={turn}
108
+ turnIndex={i}
109
+ allTurns={data.transcript}
110
+ systemPrompt={data.system_prompt}
111
+ hasMultiplePlayers={data.opponent_model !== null}
112
+ />
113
  ))}
114
  </div>
115
  </div>
 
141
  }
142
 
143
 
144
+ interface TurnBubbleProps {
145
+ turn: TranscriptTurn;
146
+ turnIndex: number;
147
+ allTurns: TranscriptTurn[];
148
+ systemPrompt: string | null;
149
+ hasMultiplePlayers: boolean;
150
+ }
151
+
152
+ function buildRawPrompt(
153
+ turnIndex: number,
154
+ allTurns: TranscriptTurn[],
155
+ systemPrompt: string | null,
156
+ ): object[] {
157
+ const messages: object[] = [];
158
+ if (systemPrompt) {
159
+ messages.push({ role: "system", content: systemPrompt });
160
+ }
161
+ for (let i = 0; i < turnIndex; i++) {
162
+ messages.push({ role: "user", content: allTurns[i].observation });
163
+ messages.push({ role: "assistant", content: allTurns[i].action });
164
+ }
165
+ messages.push({ role: "user", content: allTurns[turnIndex].observation });
166
+ return messages;
167
+ }
168
+
169
+ function TurnBubble({ turn, turnIndex, allTurns, systemPrompt, hasMultiplePlayers }: TurnBubbleProps) {
170
  const [thinkExpanded, setThinkExpanded] = useState(false);
171
+ const [rawPromptExpanded, setRawPromptExpanded] = useState(false);
172
  const playerColor = getPlayerColor(turn.player_id);
173
  const thinkSegments = highlightTrace(turn.think_text);
174
 
 
226
  </div>
227
  </div>
228
  </div>
229
+
230
+ {/* Raw Prompt — collapsible, shows full messages sent to API */}
231
+ <div className="mt-1">
232
+ <button
233
+ onClick={() => setRawPromptExpanded(!rawPromptExpanded)}
234
+ className="flex items-center gap-1 text-[10px] text-gray-600 hover:text-gray-400 transition-colors"
235
+ >
236
+ <span>{rawPromptExpanded ? "\u25BC" : "\u25B6"}</span>
237
+ <span>Raw Prompt ({turnIndex * 2 + 1 + (systemPrompt ? 1 : 0)} messages)</span>
238
+ </button>
239
+ {rawPromptExpanded && (
240
+ <pre className="mt-1 text-[10px] leading-relaxed whitespace-pre-wrap font-mono bg-gray-950 border border-gray-800 rounded px-2 py-1.5 text-gray-400 max-h-80 overflow-y-auto">
241
+ {JSON.stringify(buildRawPrompt(turnIndex, allTurns, systemPrompt), null, 2)}
242
+ </pre>
243
+ )}
244
+ </div>
245
  </div>
246
  );
247
  }