@@ -6,8 +6,11 @@ import { useParams, useRouter } from "next/navigation";
66import { Button } from "@/components/ui/button" ;
77import { Card , CardContent } from "@/components/ui/card" ;
88import { Tabs , TabsContent , TabsList , TabsTrigger } from "@/components/ui/tabs" ;
9+ import { Accordion , AccordionContent , AccordionItem , AccordionTrigger } from "@/components/ui/accordion" ;
910import { WorkflowPhase } from "@/types/agentic-session" ;
10- import { ArrowLeft , Loader2 } from "lucide-react" ;
11+ import { ArrowLeft , Loader2 , Bot } from "lucide-react" ;
12+ import { Badge } from "@/components/ui/badge" ;
13+ import { Checkbox } from "@/components/ui/checkbox" ;
1114import RepoBrowser from "@/components/RepoBrowser" ;
1215import type { GitHubFork } from "@/types" ;
1316import { Breadcrumbs } from "@/components/breadcrumbs" ;
@@ -16,7 +19,8 @@ import { RfePhaseCards } from "./rfe-phase-cards";
1619import { RfeWorkspaceCard } from "./rfe-workspace-card" ;
1720import { RfeHeader } from "./rfe-header" ;
1821import { RfeAgentsCard } from "./rfe-agents-card" ;
19- import { useRfeWorkflow , useRfeWorkflowSessions , useDeleteRfeWorkflow , useRfeWorkflowSeeding , useSeedRfeWorkflow , useUpdateRfeWorkflow , useRepoBlob , useRepoTree , useOpenJiraIssue } from "@/services/queries" ;
22+ import { AVAILABLE_AGENTS } from "@/lib/agents" ;
23+ import { useRfeWorkflow , useRfeWorkflowSessions , useDeleteRfeWorkflow , useRfeWorkflowSeeding , useSeedRfeWorkflow , useUpdateRfeWorkflow , useRepoBlob , useRepoTree , useOpenJiraIssue , useRfeWorkflowAgents } from "@/services/queries" ;
2024
2125export default function ProjectRFEDetailPage ( ) {
2226 const params = useParams ( ) ;
@@ -32,6 +36,7 @@ export default function ProjectRFEDetailPage() {
3236 const seedWorkflowMutation = useSeedRfeWorkflow ( ) ;
3337 const updateWorkflowMutation = useUpdateRfeWorkflow ( ) ;
3438 const { openJiraForPath } = useOpenJiraIssue ( project , id ) ;
39+ const { data : repoAgents = AVAILABLE_AGENTS , isLoading : loadingAgents } = useRfeWorkflowAgents ( project , id ) ;
3540
3641 // Extract repo info from workflow
3742 const repo = workflow ?. umbrellaRepo ?. url . replace ( / ^ h t t p s ? : \/ \/ (?: w w w \. ) ? g i t h u b .c o m \/ / i, '' ) . replace ( / \. g i t $ / i, '' ) || '' ;
@@ -255,8 +260,6 @@ export default function ProjectRFEDetailPage() {
255260 onDelete = { deleteWorkflow }
256261 />
257262
258-
259-
260263 < RfeWorkspaceCard
261264 workflow = { workflow }
262265 workflowWorkspace = { workflowWorkspace }
@@ -269,62 +272,140 @@ export default function ProjectRFEDetailPage() {
269272 updating = { updateWorkflowMutation . isPending }
270273 />
271274
272- < RfeAgentsCard
273- projectName = { project }
274- workflowId = { id }
275- selectedAgents = { selectedAgents }
276- onAgentsChange = { setSelectedAgents }
277- />
275+ { /* Two Column Layout */ }
276+ < div className = "grid grid-cols-1 lg:grid-cols-2 gap-6" >
277+ { /* Left Column - Tabs */ }
278+ < div className = "lg:col-span-1" >
279+ < Tabs value = { activeTab } onValueChange = { setActiveTab } >
280+ < TabsList >
281+ < TabsTrigger value = "overview" > Overview</ TabsTrigger >
282+ < TabsTrigger value = "sessions" > Sessions</ TabsTrigger >
283+ { upstreamRepo ? < TabsTrigger value = "browser" > Repository</ TabsTrigger > : null }
284+ </ TabsList >
278285
279- < Tabs value = { activeTab } onValueChange = { setActiveTab } >
280- < TabsList >
281- < TabsTrigger value = "overview" > Overview</ TabsTrigger >
282- < TabsTrigger value = "sessions" > Sessions</ TabsTrigger >
283- { upstreamRepo ? < TabsTrigger value = "browser" > Repository</ TabsTrigger > : null }
284- </ TabsList >
286+ < TabsContent value = "overview" >
287+ < RfePhaseCards
288+ workflow = { workflow }
289+ rfeSessions = { rfeSessions }
290+ rfeDoc = { rfeDoc }
291+ specKitDir = { specKitDir }
292+ firstFeaturePath = { firstFeaturePath }
293+ projectName = { project }
294+ rfeId = { id }
295+ workflowWorkspace = { workflowWorkspace }
296+ isSeeded = { isSeeded }
297+ startingPhase = { startingPhase }
298+ publishingPhase = { publishingPhase }
299+ selectedAgents = { selectedAgents }
300+ onStartPhase = { setStartingPhase }
301+ onPublishPhase = { setPublishingPhase }
302+ onLoad = { async ( ) => { await load ( ) ; } }
303+ onLoadSessions = { async ( ) => { await loadSessions ( ) ; } }
304+ onError = { setError }
305+ onOpenJira = { openJiraForPath }
306+ />
307+ </ TabsContent >
285308
286- < TabsContent value = "overview" >
287- < RfePhaseCards
288- workflow = { workflow }
289- rfeSessions = { rfeSessions }
290- rfeDoc = { rfeDoc }
291- specKitDir = { specKitDir }
292- firstFeaturePath = { firstFeaturePath }
293- projectName = { project }
294- rfeId = { id }
295- workflowWorkspace = { workflowWorkspace }
296- isSeeded = { isSeeded }
297- startingPhase = { startingPhase }
298- publishingPhase = { publishingPhase }
299- selectedAgents = { selectedAgents }
300- onStartPhase = { setStartingPhase }
301- onPublishPhase = { setPublishingPhase }
302- onLoad = { async ( ) => { await load ( ) ; } }
303- onLoadSessions = { async ( ) => { await loadSessions ( ) ; } }
304- onError = { setError }
305- onOpenJira = { openJiraForPath }
306- />
307- </ TabsContent >
309+ < TabsContent value = "sessions" >
310+ < RfeSessionsTable
311+ sessions = { rfeSessions }
312+ projectName = { project }
313+ rfeId = { id }
314+ workspacePath = { workflowWorkspace }
315+ workflowId = { workflow . id }
316+ />
317+ </ TabsContent >
308318
309- < TabsContent value = "sessions " >
310- < RfeSessionsTable
311- sessions = { rfeSessions }
312- projectName = { project }
313- rfeId = { id }
314- workspacePath = { workflowWorkspace }
315- workflowId = { workflow . id }
316- / >
317- </ TabsContent >
319+ < TabsContent value = "browser " >
320+ < RepoBrowser
321+ projectName = { project }
322+ repoUrl = { selectedFork ?. url || upstreamRepo }
323+ defaultRef = { selectedFork ?. default_branch || workflow . branchName || workflow . umbrellaRepo ?. branch || "main" }
324+ />
325+ </ TabsContent >
326+ </ Tabs >
327+ </ div >
318328
319-
320- < TabsContent value = "browser" >
321- < RepoBrowser
322- projectName = { project }
323- repoUrl = { selectedFork ?. url || upstreamRepo }
324- defaultRef = { selectedFork ?. default_branch || workflow . branchName || workflow . umbrellaRepo ?. branch || "main" }
325- />
326- </ TabsContent >
327- </ Tabs >
329+ { /* Right Column - Agents Accordion */ }
330+ < div className = "lg:col-span-1" >
331+ < Card >
332+ < CardContent className = "p-4" >
333+ < Accordion type = "multiple" className = "w-full" >
334+ < AccordionItem value = "agents" className = "border-none" >
335+ < AccordionTrigger className = "text-lg font-semibold hover:no-underline px-0" >
336+ < div className = "flex items-center gap-2" >
337+ < Bot className = "h-5 w-5" />
338+ Agents
339+ </ div >
340+ </ AccordionTrigger >
341+ < AccordionContent className = "pt-4" >
342+ { loadingAgents ? (
343+ < div className = "flex items-center justify-center py-8" >
344+ < Loader2 className = "h-6 w-6 animate-spin text-muted-foreground" />
345+ </ div >
346+ ) : repoAgents . length === 0 ? (
347+ < div className = "text-center py-8 text-muted-foreground" >
348+ < Bot className = "h-12 w-12 mx-auto mb-2 opacity-50" />
349+ < p > No agents found in repository .claude/agents directory</ p >
350+ < p className = "text-xs mt-1" > Seed the repository to add agent definitions</ p >
351+ </ div >
352+ ) : (
353+ < >
354+ < div className = "grid grid-cols-1 gap-3" >
355+ { repoAgents . map ( ( agent ) => {
356+ const isSelected = selectedAgents . includes ( agent . persona ) ;
357+ return (
358+ < div
359+ key = { agent . persona }
360+ className = { `p-3 rounded-lg border transition-colors ${
361+ isSelected ? 'bg-primary/5 border-primary' : 'bg-background border-border hover:border-primary/50'
362+ } `}
363+ >
364+ < label className = "flex items-start gap-3 cursor-pointer" >
365+ < Checkbox
366+ checked = { isSelected }
367+ onCheckedChange = { ( checked ) => {
368+ setSelectedAgents (
369+ checked
370+ ? [ ...selectedAgents , agent . persona ]
371+ : selectedAgents . filter ( p => p !== agent . persona )
372+ ) ;
373+ } }
374+ className = "mt-0.5"
375+ />
376+ < div className = "flex-1 min-w-0" >
377+ < div className = "font-medium text-sm" > { agent . name } </ div >
378+ < div className = "text-xs text-muted-foreground mt-0.5" > { agent . role } </ div >
379+ </ div >
380+ </ label >
381+ </ div >
382+ ) ;
383+ } ) }
384+ </ div >
385+ { selectedAgents . length > 0 && (
386+ < div className = "mt-4 pt-4 border-t" >
387+ < div className = "text-sm font-medium mb-2" > Selected Agents ({ selectedAgents . length } )</ div >
388+ < div className = "flex flex-wrap gap-2" >
389+ { selectedAgents . map ( persona => {
390+ const agent = repoAgents . find ( a => a . persona === persona ) ;
391+ return agent ? (
392+ < Badge key = { persona } variant = "secondary" >
393+ { agent . name }
394+ </ Badge >
395+ ) : null ;
396+ } ) }
397+ </ div >
398+ </ div >
399+ ) }
400+ </ >
401+ ) }
402+ </ AccordionContent >
403+ </ AccordionItem >
404+ </ Accordion >
405+ </ CardContent >
406+ </ Card >
407+ </ div >
408+ </ div >
328409
329410 </ div >
330411 </ div >
0 commit comments