chore: update landing and inspector content

This commit is contained in:
Nathan Flurry 2026-01-27 22:29:35 -08:00
parent c7fbb33fed
commit 30c4ad6b39
8 changed files with 128 additions and 129 deletions

View file

@ -719,7 +719,6 @@
.empty-state .button {
margin-top: 16px;
min-width: 180px;
width: auto;
}
@ -1032,8 +1031,8 @@
/* Setup Row */
.setup-row {
display: flex;
align-items: center;
gap: 8px;
align-items: flex-end;
gap: 12px;
padding: 8px 12px;
background: var(--surface-2);
border-top: 1px solid var(--border);
@ -1041,6 +1040,19 @@
flex-wrap: wrap;
}
.setup-field {
display: flex;
flex-direction: column;
gap: 4px;
}
.setup-label {
font-size: 10px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.setup-select {
background: var(--surface);
border: 1px solid var(--border-2);

View file

@ -503,16 +503,38 @@ export default function App() {
offsetRef.current = 0;
};
const handleCopy = async (entry: RequestLog) => {
try {
await navigator.clipboard.writeText(entry.curl);
const handleCopy = (entry: RequestLog) => {
const text = entry.curl;
const onSuccess = () => {
setCopiedLogId(entry.id);
window.setTimeout(() => setCopiedLogId(null), 1500);
} catch {
setCopiedLogId(null);
};
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(onSuccess).catch(() => {
fallbackCopy(text, onSuccess);
});
} else {
fallbackCopy(text, onSuccess);
}
};
const fallbackCopy = (text: string, onSuccess?: () => void) => {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.position = "fixed";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy");
onSuccess?.();
} catch (err) {
console.error("Failed to copy:", err);
}
document.body.removeChild(textarea);
};
const selectQuestionOption = (requestId: string, optionLabel: string) => {
setQuestionSelections((prev) => ({
...prev,
@ -887,9 +909,7 @@ export default function App() {
onDebugTabChange={setDebugTab}
events={events}
offset={offset}
onFetchEvents={fetchEvents}
onResetEvents={resetEvents}
eventsLoading={eventsLoading}
eventsError={eventError}
requestLog={requestLog}
copiedLogId={copiedLogId}

View file

@ -29,57 +29,69 @@ const ChatSetup = ({
}) => {
return (
<div className="setup-row">
<select
className="setup-select"
value={agentMode}
onChange={(e) => onAgentModeChange(e.target.value)}
title="Mode"
disabled={!hasSession || modesLoading || Boolean(modesError)}
>
{modesLoading ? (
<option value="">Loading modes...</option>
) : modesError ? (
<option value="">{modesError}</option>
) : activeModes.length > 0 ? (
activeModes.map((mode) => (
<option key={mode.id} value={mode.id}>
{mode.name || mode.id}
</option>
))
) : (
<option value="">Mode</option>
)}
</select>
<div className="setup-field">
<span className="setup-label">Mode</span>
<select
className="setup-select"
value={agentMode}
onChange={(e) => onAgentModeChange(e.target.value)}
title="Mode"
disabled={!hasSession || modesLoading || Boolean(modesError)}
>
{modesLoading ? (
<option value="">Loading modes...</option>
) : modesError ? (
<option value="">{modesError}</option>
) : activeModes.length > 0 ? (
activeModes.map((mode) => (
<option key={mode.id} value={mode.id}>
{mode.name || mode.id}
</option>
))
) : (
<option value="">Mode</option>
)}
</select>
</div>
<select
className="setup-select"
value={permissionMode}
onChange={(e) => onPermissionModeChange(e.target.value)}
title="Permission Mode"
disabled={!hasSession}
>
<option value="default">Default</option>
<option value="plan">Plan</option>
<option value="bypass">Bypass</option>
</select>
<div className="setup-field">
<span className="setup-label">Permission</span>
<select
className="setup-select"
value={permissionMode}
onChange={(e) => onPermissionModeChange(e.target.value)}
title="Permission Mode"
disabled={!hasSession}
>
<option value="default">Default</option>
<option value="plan">Plan</option>
<option value="bypass">Bypass</option>
</select>
</div>
<input
className="setup-input"
value={model}
onChange={(e) => onModelChange(e.target.value)}
placeholder="Model"
title="Model"
disabled={!hasSession}
/>
<div className="setup-field">
<span className="setup-label">Model</span>
<input
className="setup-input"
value={model}
onChange={(e) => onModelChange(e.target.value)}
placeholder="Model"
title="Model"
disabled={!hasSession}
/>
</div>
<input
className="setup-input"
value={variant}
onChange={(e) => onVariantChange(e.target.value)}
placeholder="Variant"
title="Variant"
disabled={!hasSession}
/>
<div className="setup-field">
<span className="setup-label">Variant</span>
<input
className="setup-input"
value={variant}
onChange={(e) => onVariantChange(e.target.value)}
placeholder="Variant"
title="Variant"
disabled={!hasSession}
/>
</div>
</div>
);
};

View file

@ -12,9 +12,7 @@ const DebugPanel = ({
onDebugTabChange,
events,
offset,
onFetchEvents,
onResetEvents,
eventsLoading,
eventsError,
requestLog,
copiedLogId,
@ -32,9 +30,7 @@ const DebugPanel = ({
onDebugTabChange: (tab: DebugTab) => void;
events: UniversalEvent[];
offset: number;
onFetchEvents: () => void;
onResetEvents: () => void;
eventsLoading: boolean;
eventsError: string | null;
requestLog: RequestLog[];
copiedLogId: number | null;
@ -80,9 +76,7 @@ const DebugPanel = ({
<EventsTab
events={events}
offset={offset}
onFetch={onFetchEvents}
onClear={onResetEvents}
loading={eventsLoading}
error={eventsError}
/>
)}

View file

@ -7,16 +7,12 @@ import { getEventCategory, getEventClass, getEventIcon, getEventKey, getEventTyp
const EventsTab = ({
events,
offset,
onFetch,
onClear,
loading,
error
}: {
events: UniversalEvent[];
offset: number;
onFetch: () => void;
onClear: () => void;
loading: boolean;
error: string | null;
}) => {
const [collapsedEvents, setCollapsedEvents] = useState<Record<string, boolean>>({});
@ -64,9 +60,6 @@ const EventsTab = ({
<div className="inline-row" style={{ marginBottom: 12, justifyContent: "space-between" }}>
<span className="card-meta">Offset: {offset}</span>
<div className="inline-row">
<button className="button ghost small" onClick={onFetch} disabled={loading}>
{loading ? "Loading..." : "Fetch"}
</button>
<button
type="button"
className="button ghost small"
@ -74,7 +67,7 @@ const EventsTab = ({
disabled={events.length === 0}
title="Copy all events as JSON"
>
{copied ? "Copied" : "Copy"}
{copied ? "Copied" : "Copy JSON"}
</button>
<button className="button ghost small" onClick={onClear}>
Clear
@ -86,7 +79,7 @@ const EventsTab = ({
{events.length === 0 ? (
<div className="card-meta">
{loading ? "Loading events..." : "No events yet. Start streaming to receive events."}
No events yet. Start streaming to receive events.
</div>
) : (
<div className="event-list">