From 88b62a3359f85b23d2bc1f5a1caf993902b1d357 Mon Sep 17 00:00:00 2001
From: Thomas Kosiewski
Date: Fri, 24 Apr 2026 20:13:10 +0200
Subject: [PATCH] fix(site/src/pages/AgentsPage): add copy buttons to raw
attempts (#24705)
---
.../DebugPanel/DebugAttemptAccordion.tsx | 26 ++++++++++---------
.../DebugPanel/DebugPanel.stories.tsx | 13 ++++++++++
.../DebugPanel/DebugPanelPrimitives.tsx | 5 +---
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugAttemptAccordion.tsx b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugAttemptAccordion.tsx
index c1c6ecf739..d75636ab86 100644
--- a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugAttemptAccordion.tsx
+++ b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugAttemptAccordion.tsx
@@ -9,7 +9,7 @@ import {
import { cn } from "#/utils/cn";
import { DATE_FORMAT, formatDateTime, humanDuration } from "#/utils/time";
import {
- DebugCodeBlock,
+ CopyableCodeBlock,
DebugDataSection,
EmptyHelper,
} from "./DebugPanelPrimitives";
@@ -27,24 +27,23 @@ interface DebugAttemptAccordionProps {
interface JsonBlockProps {
value: unknown;
- fallbackCopy: string;
+ emptyMessage: string;
+ copyLabel: string;
}
-const JsonBlock: FC = ({ value, fallbackCopy }) => {
+const JsonBlock: FC = ({ value, emptyMessage, copyLabel }) => {
if (
value === null ||
value === undefined ||
(typeof value === "string" && value.length === 0) ||
(typeof value === "object" && Object.keys(value as object).length === 0)
) {
- return ;
+ return ;
}
- if (typeof value === "string") {
- return ;
- }
+ const code = safeJsonStringify(value);
- return ;
+ return ;
};
const getAttemptTimingLabel = (attempt: NormalizedAttempt): string => {
@@ -79,7 +78,7 @@ export const DebugAttemptAccordion: FC = ({
Unable to parse raw attempts. Showing the original payload exactly as
it was captured.
-
+
);
}
@@ -161,19 +160,22 @@ export const DebugAttemptAccordion: FC = ({
diff --git a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanel.stories.tsx b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanel.stories.tsx
index e97b41b4e4..6d9930ab70 100644
--- a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanel.stories.tsx
+++ b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanel.stories.tsx
@@ -786,6 +786,19 @@ export const MultiStepRunWithRetries: Story = {
expect(canvas.getByText(/Attempt 2/)).toBeVisible();
expect(canvas.getByText(/Attempt 3/)).toBeVisible();
});
+
+ await user.click(canvas.getByRole("button", { name: /Attempt 1/i }));
+ await waitFor(() => {
+ expect(
+ canvas.getByRole("button", { name: /Copy raw request JSON/i }),
+ ).toBeVisible();
+ expect(
+ canvas.getByRole("button", { name: /Copy raw response JSON/i }),
+ ).toBeVisible();
+ expect(
+ canvas.getByRole("button", { name: /Copy raw attempt error/i }),
+ ).toBeVisible();
+ });
},
};
diff --git a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanelPrimitives.tsx b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanelPrimitives.tsx
index 1ea40266e3..9f0b00c014 100644
--- a/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanelPrimitives.tsx
+++ b/site/src/pages/AgentsPage/components/RightPanel/DebugPanel/DebugPanelPrimitives.tsx
@@ -33,10 +33,7 @@ interface DebugCodeBlockProps {
className?: string;
}
-export const DebugCodeBlock: FC = ({
- code,
- className,
-}) => {
+const DebugCodeBlock: FC = ({ code, className }) => {
return (