11"use client" ;
22
3+ import { useRef } from "react" ;
34import { Plus , Trash2 } from "lucide-react" ;
45import type { z } from "zod" ;
56
@@ -21,27 +22,46 @@ import { StringListEditor } from "./string-list-editor";
2122type AgentDef = z . infer < typeof agentDefinitionSchema > ;
2223
2324export function AgentsEditor ( { value, onChange } : { value : Record < string , AgentDef > ; onChange : ( v : Record < string , AgentDef > ) => void } ) {
25+ const nextId = useRef ( 0 ) ;
26+ const ids = useRef < number [ ] > ( [ ] ) ;
27+
2428 const entries = Object . entries ( value ) ;
29+
30+ // Sync IDs with entries length (handles external resets)
31+ while ( ids . current . length < entries . length ) {
32+ ids . current . push ( nextId . current ++ ) ;
33+ }
34+ ids . current . length = entries . length ;
35+
2536 const addAgent = ( ) => {
2637 let i = 1 ;
2738 while ( `agent-${ i } ` in value ) i ++ ;
39+ ids . current . push ( nextId . current ++ ) ;
2840 onChange ( { ...value , [ `agent-${ i } ` ] : { description : "" , prompt : "" } } ) ;
2941 } ;
30- const removeAgent = ( name : string ) => { const next = { ...value } ; delete next [ name ] ; onChange ( next ) ; } ;
31- const updateAgentName = ( oldName : string , newName : string ) => {
42+ const removeAgent = ( index : number ) => {
43+ const name = entries [ index ] [ 0 ] ;
44+ ids . current . splice ( index , 1 ) ;
45+ const next = { ...value } ;
46+ delete next [ name ] ;
47+ onChange ( next ) ;
48+ } ;
49+ const updateAgentName = ( index : number , newName : string ) => {
3250 const next : Record < string , AgentDef > = { } ;
33- for ( const [ k , v ] of Object . entries ( value ) ) next [ k === oldName ? newName : k ] = v ;
51+ for ( let i = 0 ; i < entries . length ; i ++ ) {
52+ next [ i === index ? newName : entries [ i ] [ 0 ] ] = entries [ i ] [ 1 ] ;
53+ }
3454 onChange ( next ) ;
3555 } ;
3656 const updateAgent = ( name : string , agent : AgentDef ) => onChange ( { ...value , [ name ] : agent } ) ;
3757
3858 return (
3959 < div className = "space-y-3" >
4060 < p className = "text-xs text-muted-foreground" > Define custom sub-agents with their own prompt, tools, and model.</ p >
41- { entries . map ( ( [ name , agent ] ) => (
42- < div key = { name } className = "border rounded-md p-3 space-y-3" >
61+ { entries . map ( ( [ name , agent ] , i ) => (
62+ < div key = { ids . current [ i ] } className = "border rounded-md p-3 space-y-3" >
4363 < div className = "flex items-center gap-2" >
44- < Input className = "font-mono text-xs w-1/3" value = { name } placeholder = "agent-name" onChange = { ( e ) => updateAgentName ( name , e . target . value ) } />
64+ < Input className = "font-mono text-xs w-1/3" value = { name } placeholder = "agent-name" onChange = { ( e ) => updateAgentName ( i , e . target . value ) } />
4565 < Select value = { agent . model ?? "inherit" } onValueChange = { ( m ) => updateAgent ( name , { ...agent , model : m === "inherit" ? null : m as AgentDef [ "model" ] } ) } >
4666 < SelectTrigger className = "w-32" > < SelectValue placeholder = "Model" /> </ SelectTrigger >
4767 < SelectContent >
@@ -51,7 +71,7 @@ export function AgentsEditor({ value, onChange }: { value: Record<string, AgentD
5171 < SelectItem value = "haiku" > Haiku</ SelectItem >
5272 </ SelectContent >
5373 </ Select >
54- < Button type = "button" variant = "ghost" size = "icon" className = "ml-auto h-8 w-8" aria-label = { `Remove ${ name } ` } onClick = { ( ) => removeAgent ( name ) } > < Trash2 className = "h-3 w-3" /> </ Button >
74+ < Button type = "button" variant = "ghost" size = "icon" className = "ml-auto h-8 w-8" aria-label = { `Remove ${ name } ` } onClick = { ( ) => removeAgent ( i ) } > < Trash2 className = "h-3 w-3" /> </ Button >
5575 </ div >
5676 < Input className = "text-xs" placeholder = "Description" value = { agent . description } onChange = { ( e ) => updateAgent ( name , { ...agent , description : e . target . value } ) } />
5777 < Textarea className = "font-mono text-xs" placeholder = "Agent prompt..." rows = { 3 } value = { agent . prompt } onChange = { ( e ) => updateAgent ( name , { ...agent , prompt : e . target . value } ) } />
0 commit comments