From d7b17facb6e59ddbe984fcb0f0639bd75dde31b2 Mon Sep 17 00:00:00 2001
From: Simon <10131203+gaomeng1900@users.noreply.github.com>
Date: Wed, 28 Jan 2026 15:26:11 +0800
Subject: [PATCH] feat(ext): UI for debugging
---
.../src/entrypoints/sidepanel/App.tsx | 1 +
.../sidepanel/components/cards.tsx | 122 ++++++++++++++----
2 files changed, 98 insertions(+), 25 deletions(-)
diff --git a/packages/extension/src/entrypoints/sidepanel/App.tsx b/packages/extension/src/entrypoints/sidepanel/App.tsx
index 3fc4604..5f513ca 100644
--- a/packages/extension/src/entrypoints/sidepanel/App.tsx
+++ b/packages/extension/src/entrypoints/sidepanel/App.tsx
@@ -105,6 +105,7 @@ export default function App() {
{showEmptyState && }
{history.map((event, index) => (
+ // eslint-disable-next-line react-x/no-array-index-key
))}
diff --git a/packages/extension/src/entrypoints/sidepanel/components/cards.tsx b/packages/extension/src/entrypoints/sidepanel/components/cards.tsx
index bebb6ab..296d6fb 100644
--- a/packages/extension/src/entrypoints/sidepanel/components/cards.tsx
+++ b/packages/extension/src/entrypoints/sidepanel/components/cards.tsx
@@ -8,8 +8,6 @@ import type {
} from '@page-agent/core'
import {
CheckCircle,
- ChevronDown,
- ChevronRight,
Eye,
Globe,
Keyboard,
@@ -125,27 +123,96 @@ function ActionIcon({ name, className }: { name: string; className?: string }) {
return icons[name] ||
}
-// Raw response section (collapsible, for debugging)
-function RawResponseSection({ rawResponse }: { rawResponse: unknown }) {
- const [expanded, setExpanded] = useState(false)
+// Copy button with "Copied!" feedback
+function CopyButton({ text, label }: { text: string; label: string }) {
+ const [copied, setCopied] = useState(false)
+
+ return (
+
+ )
+}
+
+// Extract message content by role from raw request
+function extractPrompt(rawRequest: unknown, role: 'system' | 'user'): string | null {
+ const messages = (rawRequest as { messages?: { role: string; content?: unknown }[] })?.messages
+ if (!messages) return null
+ const msg =
+ role === 'system'
+ ? messages.find((m) => m.role === role)
+ : messages.findLast((m) => m.role === role)
+ if (!msg?.content) return null
+ return typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content, null, 2)
+}
+
+// Raw request/response section (collapsible tabs, for debugging)
+function RawSection({ rawRequest, rawResponse }: { rawRequest?: unknown; rawResponse?: unknown }) {
+ const [activeTab, setActiveTab] = useState<'request' | 'response' | null>(null)
+
+ if (!rawRequest && !rawResponse) return null
+
+ const handleTabClick = (tab: 'request' | 'response') => {
+ setActiveTab(activeTab === tab ? null : tab)
+ }
+
+ const content =
+ activeTab === 'request' ? rawRequest : activeTab === 'response' ? rawResponse : null
+
+ const systemPrompt = activeTab === 'request' ? extractPrompt(rawRequest, 'system') : null
+ const userPrompt = activeTab === 'request' ? extractPrompt(rawRequest, 'user') : null
return (
-
- {expanded && (
-
- {JSON.stringify(rawResponse, null, 4)}
-
+
+ {rawRequest != null && (
+
+ )}
+ {rawResponse != null && (
+
+ )}
+
+ {content != null && (
+
+
+ {systemPrompt && }
+ {userPrompt && }
+
+
+
+ {JSON.stringify(content, null, 4)}
+
+
)}
)
@@ -173,7 +240,7 @@ function StepCard({ event }: { event: AgentStepEvent }) {
className="size-3.5 text-blue-500 shrink-0 mt-0.5"
/>
-
+
{event.action.name}
{event.action.name !== 'done' && (
@@ -181,14 +248,19 @@ function StepCard({ event }: { event: AgentStepEvent }) {
)}
-
└ {event.action.output}
+
+
└
+
+ {event.action.output}
+
+
)}
{/* Raw Response */}
- {!event.rawResponse || }
+
)
}
@@ -227,7 +299,7 @@ function ErrorCard({ event }: { event: AgentErrorEvent }) {
{event.message}
- {!event.rawResponse || }
+
)
}
@@ -244,7 +316,7 @@ export function EventCard({ event }: { event: HistoricalEvent }) {
success={input?.success ?? true}
text={input?.text || event.action.output || ''}
>
- {!event.rawResponse || }
+
>
)