@@ -182,80 +182,6 @@ function NewTabPopover({ open, onClose, anchorRef, discoverAgents, onFromScratch
182182 ) ;
183183}
184184
185- // --- LoadAgentPopover ---
186- interface LoadAgentPopoverProps {
187- open : boolean ;
188- onClose : ( ) => void ;
189- anchorRef : React . RefObject < HTMLButtonElement | null > ;
190- discoverAgents : DiscoverEntry [ ] ;
191- onSelect : ( agentPath : string ) => void ;
192- }
193-
194- function LoadAgentPopover ( { open, onClose, anchorRef, discoverAgents, onSelect } : LoadAgentPopoverProps ) {
195- const [ pos , setPos ] = useState < { top : number ; right : number } | null > ( null ) ;
196- const ref = useRef < HTMLDivElement > ( null ) ;
197-
198- useEffect ( ( ) => {
199- if ( open && anchorRef . current ) {
200- const rect = anchorRef . current . getBoundingClientRect ( ) ;
201- setPos ( { top : rect . bottom + 4 , right : window . innerWidth - rect . right } ) ;
202- }
203- } , [ open , anchorRef ] ) ;
204-
205- useEffect ( ( ) => {
206- if ( ! open ) return ;
207- const handler = ( e : MouseEvent ) => {
208- if (
209- ref . current && ! ref . current . contains ( e . target as Node ) &&
210- anchorRef . current && ! anchorRef . current . contains ( e . target as Node )
211- ) onClose ( ) ;
212- } ;
213- document . addEventListener ( "mousedown" , handler ) ;
214- return ( ) => document . removeEventListener ( "mousedown" , handler ) ;
215- } , [ open , onClose , anchorRef ] ) ;
216-
217- useEffect ( ( ) => {
218- if ( ! open ) return ;
219- const handler = ( e : KeyboardEvent ) => { if ( e . key === "Escape" ) onClose ( ) ; } ;
220- document . addEventListener ( "keydown" , handler ) ;
221- return ( ) => document . removeEventListener ( "keydown" , handler ) ;
222- } , [ open , onClose ] ) ;
223-
224- if ( ! open || ! pos ) return null ;
225-
226- return ReactDOM . createPortal (
227- < div
228- ref = { ref }
229- style = { { position : "fixed" , top : pos . top , right : pos . right , zIndex : 9999 } }
230- className = "w-60 rounded-xl border border-border/60 bg-card shadow-xl shadow-black/30 overflow-hidden"
231- >
232- < div className = "flex items-center gap-2 px-3 py-2.5 border-b border-border/40" >
233- < span className = "text-xs font-semibold text-muted-foreground uppercase tracking-wider" >
234- Load Agent
235- </ span >
236- </ div >
237- < div className = "p-1.5 flex flex-col max-h-64 overflow-y-auto" >
238- { discoverAgents . map ( agent => (
239- < button
240- key = { agent . path }
241- onClick = { ( ) => { onSelect ( agent . path ) ; onClose ( ) ; } }
242- className = "flex items-center gap-2.5 w-full px-3 py-2 rounded-lg text-left transition-colors hover:bg-muted/60 text-foreground"
243- >
244- < div className = "w-6 h-6 rounded-md bg-muted/80 flex items-center justify-center flex-shrink-0" >
245- < Bot className = "w-3.5 h-3.5 text-muted-foreground" />
246- </ div >
247- < span className = "text-sm font-medium" > { agent . name } </ span >
248- </ button >
249- ) ) }
250- { discoverAgents . length === 0 && (
251- < p className = "text-xs text-muted-foreground px-3 py-2" > No agents found</ p >
252- ) }
253- </ div >
254- </ div > ,
255- document . body
256- ) ;
257- }
258-
259185function fmtLogTs ( ts : string ) : string {
260186 try {
261187 const d = new Date ( ts ) ;
@@ -399,9 +325,6 @@ export default function Workspace() {
399325 const [ selectedNode , setSelectedNode ] = useState < GraphNode | null > ( null ) ;
400326 const [ newTabOpen , setNewTabOpen ] = useState ( false ) ;
401327 const newTabBtnRef = useRef < HTMLButtonElement > ( null ) ;
402- const [ loadAgentOpen , setLoadAgentOpen ] = useState ( false ) ;
403- const [ loadingWorker , setLoadingWorker ] = useState ( false ) ;
404- const loadAgentBtnRef = useRef < HTMLButtonElement > ( null ) ;
405328
406329 // Ref mirror of sessionsByAgent so SSE callback can read current graph
407330 // state without adding sessionsByAgent to its dependency array.
@@ -1458,42 +1381,6 @@ export default function Workspace() {
14581381 }
14591382 } , [ activeWorker , activeSession , agentStates , updateAgentState ] ) ;
14601383
1461- const handleLoadAgent = useCallback ( async ( agentPath : string ) => {
1462- const state = agentStates [ activeWorker ] ;
1463- if ( ! state ?. sessionId ) return ;
1464-
1465- setLoadingWorker ( true ) ;
1466- try {
1467- await sessionsApi . loadWorker ( state . sessionId , agentPath ) ;
1468- // Success: worker_loaded SSE event will handle UI updates automatically
1469- } catch ( err ) {
1470- // 424 = credentials required — open the credentials modal
1471- if ( err instanceof ApiError && err . status === 424 ) {
1472- const body = err . body as Record < string , unknown > ;
1473- setCredentialAgentPath ( ( body . agent_path as string ) || null ) ;
1474- setCredentialsOpen ( true ) ;
1475- setLoadingWorker ( false ) ;
1476- return ;
1477- }
1478-
1479- const errMsg = err instanceof Error ? err . message : String ( err ) ;
1480- const activeId = activeSessionRef . current [ activeWorker ] ;
1481- const errorMsg : ChatMessage = {
1482- id : makeId ( ) , agent : "System" , agentColor : "" ,
1483- content : `Failed to load agent: ${ errMsg } ` ,
1484- timestamp : "" , type : "system" , thread : activeWorker ,
1485- } ;
1486- setSessionsByAgent ( prev => ( {
1487- ...prev ,
1488- [ activeWorker ] : ( prev [ activeWorker ] || [ ] ) . map ( s =>
1489- s . id === activeId ? { ...s , messages : [ ...s . messages , errorMsg ] } : s
1490- ) ,
1491- } ) ) ;
1492- } finally {
1493- setLoadingWorker ( false ) ;
1494- }
1495- } , [ activeWorker , agentStates ] ) ;
1496-
14971384 const closeAgentTab = useCallback ( ( agentType : string ) => {
14981385 setSelectedNode ( null ) ;
14991386 // Pause worker execution if running (saves checkpoint), then kill the
@@ -1592,30 +1479,6 @@ export default function Workspace() {
15921479 </ >
15931480 }
15941481 >
1595- { activeWorker === "new-agent" && activeAgentState ?. ready && ! activeAgentState ?. graphId && (
1596- < >
1597- < button
1598- ref = { loadAgentBtnRef }
1599- onClick = { ( ) => setLoadAgentOpen ( o => ! o ) }
1600- disabled = { loadingWorker }
1601- className = "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors flex-shrink-0"
1602- >
1603- { loadingWorker ? (
1604- < Loader2 className = "w-3.5 h-3.5 animate-spin" />
1605- ) : (
1606- < Bot className = "w-3.5 h-3.5" />
1607- ) }
1608- Load Agent
1609- </ button >
1610- < LoadAgentPopover
1611- open = { loadAgentOpen }
1612- onClose = { ( ) => setLoadAgentOpen ( false ) }
1613- anchorRef = { loadAgentBtnRef }
1614- discoverAgents = { discoverAgents }
1615- onSelect = { handleLoadAgent }
1616- />
1617- </ >
1618- ) }
16191482 < button
16201483 onClick = { ( ) => setCredentialsOpen ( true ) }
16211484 className = "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors flex-shrink-0"
0 commit comments