@@ -9,16 +9,18 @@ import { createSignal, For, onMount, Show, createEffect } from "solid-js"
99import { useKeyboard , useTerminalDimensions } from "@opentui/solid"
1010import { useTheme } from "@tui/shared/context/theme"
1111import type { TrackConfig , ConditionConfig } from "../../../../workflows/templates/types"
12+ import type { AgentDefinition } from "../../../../shared/agents/config/types"
1213
1314export interface OnboardProps {
1415 tracks ?: Record < string , TrackConfig >
1516 conditions ?: Record < string , ConditionConfig >
17+ controllerAgents ?: AgentDefinition [ ] // Available controller agents
1618 initialProjectName ?: string | null // If set, skip project name input
17- onComplete : ( result : { projectName ?: string ; trackId ?: string ; conditions ?: string [ ] } ) => void
19+ onComplete : ( result : { projectName ?: string ; trackId ?: string ; conditions ?: string [ ] ; controllerAgentId ?: string } ) => void
1820 onCancel ?: ( ) => void
1921}
2022
21- type OnboardStep = 'project_name' | 'tracks' | 'conditions'
23+ type OnboardStep = 'project_name' | 'tracks' | 'conditions' | 'controller'
2224
2325export function Onboard ( props : OnboardProps ) {
2426 const themeCtx = useTheme ( )
@@ -32,9 +34,11 @@ export function Onboard(props: OnboardProps) {
3234 const [ projectName , setProjectName ] = createSignal ( "" )
3335 const [ selectedTrackId , setSelectedTrackId ] = createSignal < string | undefined > ( )
3436 const [ selectedConditions , setSelectedConditions ] = createSignal < Set < string > > ( new Set ( ) )
37+ const [ selectedControllerId , setSelectedControllerId ] = createSignal < string | undefined > ( )
3538
3639 const hasTracks = ( ) => props . tracks && Object . keys ( props . tracks ) . length > 0
3740 const hasConditions = ( ) => props . conditions && Object . keys ( props . conditions ) . length > 0
41+ const hasControllers = ( ) => props . controllerAgents && props . controllerAgents . length > 0
3842
3943 // Determine initial step - skip project_name if already set
4044 onMount ( ( ) => {
@@ -44,6 +48,8 @@ export function Onboard(props: OnboardProps) {
4448 setCurrentStep ( 'tracks' )
4549 } else if ( hasConditions ( ) ) {
4650 setCurrentStep ( 'conditions' )
51+ } else if ( hasControllers ( ) ) {
52+ setCurrentStep ( 'controller' )
4753 } else {
4854 props . onComplete ( { projectName : props . initialProjectName } )
4955 }
@@ -53,18 +59,28 @@ export function Onboard(props: OnboardProps) {
5359 const projectNameQuestion = "What is your project name?"
5460 const trackQuestion = "What is your project size?"
5561 const conditionsQuestion = "What features does your project have?"
62+ const controllerQuestion = "Select a controller agent for autonomous mode:"
5663
5764 const trackEntries = ( ) => props . tracks ? Object . entries ( props . tracks ) : [ ]
5865 const conditionEntries = ( ) => props . conditions ? Object . entries ( props . conditions ) : [ ]
66+ const controllerEntries = ( ) => props . controllerAgents ? props . controllerAgents . map ( a => [ a . id , a ] as const ) : [ ]
5967
6068 const currentQuestion = ( ) => {
6169 switch ( currentStep ( ) ) {
6270 case 'project_name' : return projectNameQuestion
6371 case 'tracks' : return trackQuestion
6472 case 'conditions' : return conditionsQuestion
73+ case 'controller' : return controllerQuestion
74+ }
75+ }
76+ const currentEntries = ( ) => {
77+ switch ( currentStep ( ) ) {
78+ case 'tracks' : return trackEntries ( )
79+ case 'conditions' : return conditionEntries ( )
80+ case 'controller' : return controllerEntries ( )
81+ default : return [ ]
6582 }
6683 }
67- const currentEntries = ( ) => currentStep ( ) === 'tracks' ? trackEntries ( ) : conditionEntries ( )
6884
6985 // Typing effect - reset when step changes
7086 createEffect ( ( ) => {
@@ -96,6 +112,8 @@ export function Onboard(props: OnboardProps) {
96112 setCurrentStep ( 'tracks' )
97113 } else if ( hasConditions ( ) ) {
98114 setCurrentStep ( 'conditions' )
115+ } else if ( hasControllers ( ) ) {
116+ setCurrentStep ( 'controller' )
99117 } else {
100118 props . onComplete ( { projectName : name } )
101119 }
@@ -105,16 +123,32 @@ export function Onboard(props: OnboardProps) {
105123 setSelectedTrackId ( trackId )
106124 if ( hasConditions ( ) ) {
107125 setCurrentStep ( 'conditions' )
126+ } else if ( hasControllers ( ) ) {
127+ setCurrentStep ( 'controller' )
108128 } else {
109129 props . onComplete ( { projectName : projectName ( ) , trackId } )
110130 }
111131 }
112132
113133 const handleConditionsComplete = ( ) => {
134+ if ( hasControllers ( ) ) {
135+ setCurrentStep ( 'controller' )
136+ } else {
137+ props . onComplete ( {
138+ projectName : projectName ( ) ,
139+ trackId : selectedTrackId ( ) ,
140+ conditions : Array . from ( selectedConditions ( ) )
141+ } )
142+ }
143+ }
144+
145+ const handleControllerSelect = ( controllerId : string ) => {
146+ setSelectedControllerId ( controllerId )
114147 props . onComplete ( {
115148 projectName : projectName ( ) ,
116149 trackId : selectedTrackId ( ) ,
117- conditions : Array . from ( selectedConditions ( ) )
150+ conditions : Array . from ( selectedConditions ( ) ) ,
151+ controllerAgentId : controllerId
118152 } )
119153 }
120154
@@ -164,11 +198,14 @@ export function Onboard(props: OnboardProps) {
164198 evt . preventDefault ( )
165199 if ( step === 'tracks' ) {
166200 const [ trackId ] = entries [ selectedIndex ( ) ]
167- handleTrackSelect ( trackId )
201+ handleTrackSelect ( trackId as string )
202+ } else if ( step === 'controller' ) {
203+ const [ controllerId ] = entries [ selectedIndex ( ) ]
204+ handleControllerSelect ( controllerId as string )
168205 } else {
169206 // In conditions step, Enter toggles the checkbox
170207 const [ conditionId ] = entries [ selectedIndex ( ) ]
171- toggleCondition ( conditionId )
208+ toggleCondition ( conditionId as string )
172209 }
173210 } else if ( evt . name === "tab" && step === 'conditions' ) {
174211 evt . preventDefault ( )
@@ -182,10 +219,13 @@ export function Onboard(props: OnboardProps) {
182219 evt . preventDefault ( )
183220 if ( step === 'tracks' ) {
184221 const [ trackId ] = entries [ num - 1 ]
185- handleTrackSelect ( trackId )
222+ handleTrackSelect ( trackId as string )
223+ } else if ( step === 'controller' ) {
224+ const [ controllerId ] = entries [ num - 1 ]
225+ handleControllerSelect ( controllerId as string )
186226 } else {
187227 const [ conditionId ] = entries [ num - 1 ]
188- toggleCondition ( conditionId )
228+ toggleCondition ( conditionId as string )
189229 }
190230 }
191231 }
@@ -309,6 +349,29 @@ export function Onboard(props: OnboardProps) {
309349 } }
310350 </ For >
311351 </ Show >
352+
353+ < Show when = { currentStep ( ) === 'controller' } >
354+ < For each = { controllerEntries ( ) } >
355+ { ( [ controllerId , agent ] , index ) => {
356+ const isSelected = ( ) => index ( ) === selectedIndex ( )
357+ return (
358+ < box flexDirection = "column" >
359+ < box flexDirection = "row" gap = { 1 } >
360+ < text fg = { isSelected ( ) ? themeCtx . theme . primary : themeCtx . theme . textMuted } >
361+ { isSelected ( ) ? ">" : " " }
362+ </ text >
363+ < text fg = { isSelected ( ) ? themeCtx . theme . primary : themeCtx . theme . textMuted } >
364+ { isSelected ( ) ? "(*)" : "( )" }
365+ </ text >
366+ < text fg = { isSelected ( ) ? themeCtx . theme . primary : themeCtx . theme . text } >
367+ { controllerId }
368+ </ text >
369+ </ box >
370+ </ box >
371+ )
372+ } }
373+ </ For >
374+ </ Show >
312375 </ box >
313376
314377 { /* Footer */ }
@@ -328,6 +391,11 @@ export function Onboard(props: OnboardProps) {
328391 [Up/Down] Navigate [Enter] Toggle [Tab] Confirm [Esc] Cancel
329392 </ text >
330393 </ Show >
394+ < Show when = { currentStep ( ) === 'controller' } >
395+ < text fg = { themeCtx . theme . textMuted } >
396+ [Up/Down] Navigate [Enter] Select [Esc] Cancel
397+ </ text >
398+ </ Show >
331399 </ box >
332400 </ box >
333401 </ box >
0 commit comments