mirror of
https://github.com/usestrix/strix.git
synced 2026-09-10 22:41:11 +00:00
Open agent details in a modal
This commit is contained in:
parent
46e4b16167
commit
db29c77b30
6 changed files with 178 additions and 110 deletions
File diff suppressed because one or more lines are too long
10
strix/viewer/viewer_dist/assets/index-Di2TwyAB.css
Normal file
10
strix/viewer/viewer_dist/assets/index-Di2TwyAB.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -6,8 +6,8 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="color-scheme" content="dark" />
|
||||
<title>Strix Results</title>
|
||||
<script type="module" crossorigin src="./assets/index-C0ezPxZx.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-nWrlYz6N.css">
|
||||
<script type="module" crossorigin src="./assets/index-BQfxrWUY.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-Di2TwyAB.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ import VulnerabilityDetail from "@/components/vulnerability/VulnerabilityDetail"
|
|||
import { ContentSection } from "@/components/vulnerability/ContentSection";
|
||||
import { IssueSeveritySummary } from "@/components/IssueSeveritySummary";
|
||||
import AgentGraph from "@/components/live/AgentGraph";
|
||||
import { AgentTranscript, buildGraphAgents } from "@/components/live/AgentTranscript";
|
||||
import { buildGraphAgents } from "@/components/live/AgentTranscript";
|
||||
import AgentDetailModal from "@/components/live/AgentDetailModal";
|
||||
import { severityCounts, type ParsedRunSummary } from "@/lib/local-run-parser";
|
||||
import { fetchAll, fetchRunSummary, fetchTranscript, fetchVulnerabilities, type LoadedRun } from "@/data/serverSource";
|
||||
|
||||
|
|
@ -456,12 +457,10 @@ function UpsellRow() {
|
|||
function AgentsTab({ run }: { run: LoadedRun }) {
|
||||
const { agents, events } = run.transcript;
|
||||
const graphAgents = useMemo(() => buildGraphAgents(agents, events), [agents, events]);
|
||||
// Default the transcript to the root agent (no parent) so something is always
|
||||
// shown; the graph selection then drives which agent's transcript renders.
|
||||
const rootId = useMemo(() => agents.find((a) => !a.parent_id)?.id ?? agents[0]?.id ?? null, [agents]);
|
||||
// Clicking a graph node opens the agent's transcript in a modal (matching the
|
||||
// cloud app); no node selected means no modal.
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const activeId = selectedId ?? rootId;
|
||||
const activeAgent = agents.find((a) => a.id === activeId) ?? null;
|
||||
const selectedAgent = selectedId ? (agents.find((a) => a.id === selectedId) ?? null) : null;
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
|
|
@ -474,12 +473,12 @@ function AgentsTab({ run }: { run: LoadedRun }) {
|
|||
</span>
|
||||
</div>
|
||||
<p className="mt-1 mb-4 text-xs text-[#666]">
|
||||
Select an agent to view its full transcript below.
|
||||
Click an agent to open its full transcript.
|
||||
</p>
|
||||
<div className="h-[480px] rounded-lg border border-[#1a1a1a] overflow-hidden">
|
||||
<AgentGraph
|
||||
agents={graphAgents}
|
||||
selectedAgentId={activeId}
|
||||
selectedAgentId={selectedId}
|
||||
onSelectAgent={(id) => setSelectedId(id)}
|
||||
eventsLoaded
|
||||
eventsEmpty={graphAgents.size === 0}
|
||||
|
|
@ -488,10 +487,12 @@ function AgentsTab({ run }: { run: LoadedRun }) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{activeAgent && (
|
||||
<div className="rounded-xl border border-[#222] bg-[rgba(255,255,255,0.02)] p-5">
|
||||
<AgentTranscript agent={activeAgent} events={events} />
|
||||
</div>
|
||||
{selectedAgent && (
|
||||
<AgentDetailModal
|
||||
agent={selectedAgent}
|
||||
events={events}
|
||||
onClose={() => setSelectedId(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
62
strix/viewer_src/src/components/live/AgentDetailModal.tsx
Normal file
62
strix/viewer_src/src/components/live/AgentDetailModal.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { useEffect } from "react";
|
||||
import { X } from "lucide-react";
|
||||
import { AgentTranscript } from "./AgentTranscript";
|
||||
import type { TranscriptAgent, TranscriptEvent } from "@/data/serverSource";
|
||||
|
||||
/**
|
||||
* Overlay modal showing a single agent's full transcript. Matches the cloud
|
||||
* app, where clicking a node in the agent graph opens a modal (rather than
|
||||
* revealing a section beneath the graph). Closes on backdrop click, the X
|
||||
* button, or Escape.
|
||||
*/
|
||||
export function AgentDetailModal({
|
||||
agent,
|
||||
events,
|
||||
onClose,
|
||||
}: {
|
||||
agent: TranscriptAgent;
|
||||
events: TranscriptEvent[];
|
||||
onClose: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") onClose();
|
||||
};
|
||||
document.addEventListener("keydown", onKey);
|
||||
const prevOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = "hidden";
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKey);
|
||||
document.body.style.overflow = prevOverflow;
|
||||
};
|
||||
}, [onClose]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/70 p-4 sm:p-8"
|
||||
onClick={onClose}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label={`Agent ${agent.name}`}
|
||||
>
|
||||
<div
|
||||
className="relative my-auto w-full max-w-3xl rounded-xl border border-[#222] bg-[#0a0a0a] shadow-2xl"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
aria-label="Close"
|
||||
className="absolute right-3 top-3 z-10 rounded-md p-1 text-[#888] transition-colors hover:bg-[#1a1a1a] hover:text-white"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
<div className="max-h-[85vh] overflow-y-auto p-5">
|
||||
<AgentTranscript agent={agent} events={events} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AgentDetailModal;
|
||||
Loading…
Add table
Reference in a new issue