2727COLOR_BORDER = Color (90 )
2828COLOR_MAIN = Color (220 )
2929COLOR_TITLE = Color (220 , 100 , 40 , reversed = True )
30- COLOR_ERROR = Color (0 , 50 )
30+ COLOR_ERROR = Color (0 , 70 )
3131COLOR_BANNER = Color (80 , 80 , 80 )
3232COLOR_FORM = Color (300 )
3333COLOR_FORM_BORDER = Color (300 , 80 )
@@ -120,10 +120,10 @@ def __init__(self, coords: tuple[int, int], dims: tuple[int, int]) -> None:
120120 self .color = Color (0 , 0 , 70 )
121121 self .value = " | " .join (
122122 [
123- "[tab] to select " ,
124- "[up / down] to navigate " ,
125- "[space / enter] to confirm " ,
126- "[q] to quit " ,
123+ "select [tab]" ,
124+ "navigate [up / down]" ,
125+ "confirm [space / enter]" ,
126+ "[q]uit " ,
127127 ]
128128 )
129129 if conf .DEBUG :
@@ -148,68 +148,41 @@ def _get_color(self) -> Color:
148148 )
149149
150150 def layout (self ) -> list [Renderable ]:
151- buttons = []
151+ buttons_conf : dict [ str , Callable ] = {}
152152
153153 if not self .app .state .project :
154154 # no project yet, so we need to create one
155- buttons .append (
156- Button (
157- # center button full width below the subtitle
158- (round (self .height / 2 ) + (len (buttons ) * 4 ), round (self .width / 2 / 2 )),
159- (3 , round (self .width / 2 )),
160- "Create Project" ,
161- color = COLOR_BUTTON ,
162- on_confirm = lambda : self .app .load ('project' , workflow = 'project' ),
163- )
164- )
155+ buttons_conf ["Create Project" ] = lambda : self .app .load ('project' , workflow = 'project' )
165156 else :
166157 # project has been created, so we can add agents
167- buttons .append (
168- Button (
169- (round (self .height / 2 ) + (len (buttons ) * 4 ), round (self .width / 2 / 2 )),
170- (3 , round (self .width / 2 )),
171- "Add Agent" ,
172- color = COLOR_BUTTON ,
173- on_confirm = lambda : self .app .load ('agent' , workflow = 'agent' ),
174- )
175- )
158+ buttons_conf ["New Agent" ] = lambda : self .app .load ('agent' , workflow = 'agent' )
176159
177160 if len (self .app .state .agents ):
178161 # we have one or more agents, so we can add tasks
179- buttons .append (
180- Button (
181- (round (self .height / 2 ) + (len (buttons ) * 4 ), round (self .width / 2 / 2 )),
182- (3 , round (self .width / 2 )),
183- "Add Task" ,
184- color = COLOR_BUTTON ,
185- on_confirm = lambda : self .app .load ('task' , workflow = 'task' ),
186- )
187- )
188-
162+ buttons_conf ["New Task" ] = lambda : self .app .load ('task' , workflow = 'task' )
189163 # we can also add more tools to existing agents
190- buttons .append (
191- Button (
192- (round (self .height / 2 ) + (len (buttons ) * 4 ), round (self .width / 2 / 2 )),
193- (3 , round (self .width / 2 )),
194- "Add More Tools" ,
195- color = COLOR_BUTTON ,
196- on_confirm = lambda : self .app .load ('tool_agent_selection' , workflow = 'tool' ),
197- )
198- )
199-
200-
201-
164+ buttons_conf ["Add Tools" ] = lambda : self .app .load ('tool_agent_selection' , workflow = 'tool' )
165+
202166 if self .app .state .project :
203167 # we can complete the project
168+ buttons_conf ["Finish" ] = lambda : self .app .finish ()
169+
170+ buttons : list [Button ] = []
171+ num_buttons = len (buttons_conf )
172+ button_width = min (round (self .width / 2 ), round (self .width / num_buttons ) - 2 )
173+ left_offset = round ((self .width - (num_buttons * button_width )) / 2 ) if num_buttons == 1 else 2
174+
175+ for title , action in buttons_conf .items ():
204176 buttons .append (
205177 Button (
206- (round ( self .height / 2 ) + ( len ( buttons ) * 4 ), round ( self . width / 2 / 2 ) ),
207- (3 , round ( self . width / 2 ) ),
208- "Finish" ,
178+ (self .height - 5 , left_offset ),
179+ (3 , button_width ),
180+ title ,
209181 color = COLOR_BUTTON ,
210- on_confirm = lambda : self . app . finish () ,
182+ on_confirm = action ,
211183 )
212184 )
185+ left_offset += button_width + 1
213186
214187 return [
215188 StarBox (
@@ -219,7 +192,7 @@ def layout(self) -> list[Renderable]:
219192 modules = [
220193 LogoElement ((1 , 1 ), (7 , self .width - 2 )),
221194 Box (
222- (round (self .height / 4 ), round (self .width / 4 )),
195+ (round (self .height / 3 ), round (self .width / 4 )),
223196 (9 , round (self .width / 2 )),
224197 color = COLOR_BANNER ,
225198 modules = [
@@ -276,11 +249,11 @@ def layout(self) -> list[Renderable]:
276249 color = COLOR_BORDER ,
277250 modules = [
278251 LogoElement ((1 , 1 ), (7 , self .width - 2 )),
279- Title ((9 , 1 ), (1 , self .width - 3 ), color = COLOR_TITLE , value = self .title ),
280- Title ((10 , 1 ) , (1 , self .width - 3 ), color = COLOR_ERROR , value = self .error_message ),
252+ Title ((9 , 1 ), (1 , self .width - 2 ), color = COLOR_TITLE , value = self .title ),
253+ Title ((self . height - 5 , round ( self . width / 3 )) , (3 , round ( self .width / 3 ) ), color = COLOR_ERROR , value = self .error_message ),
281254 * self .form (),
282255 Button (
283- (self .height - 6 , self .width - 17 ),
256+ (self .height - 5 , self .width - 17 ),
284257 (3 , 15 ),
285258 "Next" ,
286259 color = COLOR_BUTTON ,
@@ -321,17 +294,17 @@ def submit(self):
321294 def form (self ) -> list [Renderable ]:
322295 return [
323296 RadioSelect (
324- (12 , 1 ),
325- (self .height - 18 , round (self .width / 2 ) - 3 ),
297+ (10 , 1 ),
298+ (self .height - 15 , round (self .width / 2 ) - 2 ),
326299 options = self .get_agent_options (),
327300 color = COLOR_FORM_BORDER ,
328301 highlight = ColorAnimation (COLOR_BUTTON .sat (0 ), COLOR_BUTTON , duration = 0.2 ),
329302 on_change = self .set_agent_selection ,
330303 on_select = self .set_agent_choice ,
331304 ),
332305 Box (
333- (12 , round (self .width / 2 )),
334- (self .height - 18 , round (self .width / 2 ) - 3 ),
306+ (10 , round (self .width / 2 ) + 1 ),
307+ (self .height - 15 , round (self .width / 2 ) - 2 ),
335308 color = COLOR_FORM_BORDER ,
336309 modules = [
337310 ASCIIText (
@@ -343,7 +316,7 @@ def form(self) -> list[Renderable]:
343316 BoldText ((5 , 3 ), (1 , round (self .width / 2 ) - 10 ), color = COLOR_FORM , value = self .agent_llm ),
344317 WrappedText (
345318 (7 , 3 ),
346- (5 , round (self .width / 2 ) - 10 ),
319+ (min ( 5 , self . height - 24 ) , round (self .width / 2 ) - 10 ),
347320 color = COLOR_FORM .sat (50 ),
348321 value = self .agent_description ,
349322 ),
@@ -377,10 +350,10 @@ def submit(self):
377350
378351 def form (self ) -> list [Renderable ]:
379352 return [
380- Text ((12 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Name" ),
381- TextInput ((12 , 14 ), (2 , self .width - 15 ), self .project_name , ** FIELD_COLORS ),
382- Text ((14 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Description" ),
383- TextInput ((14 , 14 ), (5 , self .width - 15 ), self .project_description , ** FIELD_COLORS ),
353+ Text ((11 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Name" ),
354+ TextInput ((11 , 14 ), (2 , self .width - 15 ), self .project_name , ** FIELD_COLORS ),
355+ Text ((13 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Description" ),
356+ TextInput ((13 , 14 ), (5 , self .width - 15 ), self .project_description , ** FIELD_COLORS ),
384357 ]
385358
386359
@@ -417,17 +390,17 @@ def submit(self):
417390 def form (self ) -> list [Renderable ]:
418391 return [
419392 RadioSelect (
420- (12 , 1 ),
421- (self .height - 18 , round (self .width / 2 ) - 3 ),
393+ (10 , 1 ),
394+ (self .height - 15 , round (self .width / 2 ) - 2 ),
422395 options = list (self .framework_options .keys ()),
423396 color = COLOR_FORM_BORDER ,
424397 highlight = ColorAnimation (COLOR_BUTTON .sat (0 ), COLOR_BUTTON , duration = 0.2 ),
425398 on_change = self .set_framework_selection ,
426399 on_select = self .set_framework_choice ,
427400 ),
428401 Box (
429- (12 , round (self .width / 2 )),
430- (self .height - 18 , round (self .width / 2 ) - 3 ),
402+ (10 , round (self .width / 2 )),
403+ (self .height - 15 , round (self .width / 2 ) - 2 ),
431404 color = COLOR_FORM_BORDER ,
432405 modules = [
433406 ASCIIText (
@@ -441,7 +414,7 @@ def form(self) -> list[Renderable]:
441414 ),
442415 WrappedText (
443416 (7 , 3 ),
444- (5 , round (self .width / 2 ) - 10 ),
417+ (min ( 5 , self . height - 24 ) , round (self .width / 2 ) - 10 ),
445418 color = COLOR_FORM .sat (50 ),
446419 value = self .framework_description ,
447420 ),
@@ -493,15 +466,19 @@ def submit(self):
493466 self .app .advance ()
494467
495468 def form (self ) -> list [Renderable ]:
469+ large_field_height = min (5 , round ((self .height - 17 ) / 3 ))
496470 return [
497- Text ((12 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Name" ),
498- TextInput ((12 , 13 ), (2 , self .width - 15 ), self .agent_name , ** FIELD_COLORS ),
499- Text ((14 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Role" ),
500- TextInput ((14 , 13 ), (5 , self .width - 15 ), self .agent_role , ** FIELD_COLORS ),
501- Text ((19 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Goal" ),
502- TextInput ((19 , 13 ), (5 , self .width - 15 ), self .agent_goal , ** FIELD_COLORS ),
503- Text ((24 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Backstory" ),
504- TextInput ((24 , 13 ), (5 , self .width - 15 ), self .agent_backstory , ** FIELD_COLORS ),
471+ Text ((11 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Name" ),
472+ TextInput ((11 , 14 ), (2 , self .width - 16 ), self .agent_name , ** FIELD_COLORS ),
473+
474+ Text ((13 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Role" ),
475+ TextInput ((13 , 14 ), (large_field_height , self .width - 16 ), self .agent_role , ** FIELD_COLORS ),
476+
477+ Text ((13 + large_field_height , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Goal" ),
478+ TextInput ((13 + large_field_height , 14 ), (large_field_height , self .width - 16 ), self .agent_goal , ** FIELD_COLORS ),
479+
480+ Text ((13 + (large_field_height * 2 ), 2 ), (1 , 12 ), color = COLOR_FORM , value = "Backstory" ),
481+ TextInput ((13 + (large_field_height * 2 ), 14 ), (large_field_height , self .width - 16 ), self .agent_backstory , ** FIELD_COLORS ),
505482 ]
506483
507484
@@ -542,17 +519,17 @@ def submit(self):
542519 def form (self ) -> list [Renderable ]:
543520 return [
544521 RadioSelect (
545- (11 , 1 ),
546- (self .height - 18 , round (self .width / 2 ) - 3 ),
522+ (10 , 1 ),
523+ (self .height - 15 , round (self .width / 2 ) - 2 ),
547524 options = self .get_model_options (),
548525 color = COLOR_FORM_BORDER ,
549526 highlight = ColorAnimation (COLOR_BUTTON .sat (0 ), COLOR_BUTTON , duration = 0.2 ),
550527 on_change = self .set_model_selection ,
551528 on_select = self .set_model_choice ,
552529 ),
553530 Box (
554- (11 , round (self .width / 2 )),
555- (self .height - 18 , round (self .width / 2 ) - 3 ),
531+ (10 , round (self .width / 2 )),
532+ (self .height - 15 , round (self .width / 2 ) - 2 ),
556533 color = COLOR_FORM_BORDER ,
557534 modules = [
558535 ASCIIText (
@@ -566,7 +543,7 @@ def form(self) -> list[Renderable]:
566543 ),
567544 WrappedText (
568545 (7 , 3 ),
569- (5 , round (self .width / 2 ) - 10 ),
546+ (min ( 5 , self . height - 24 ) , round (self .width / 2 ) - 10 ),
570547 color = COLOR_FORM .sat (50 ),
571548 value = self .model_description ,
572549 ),
@@ -612,17 +589,17 @@ def skip(self):
612589 def form (self ) -> list [Renderable ]:
613590 return [
614591 RadioSelect (
615- (11 , 1 ),
616- (self .height - 18 , round (self .width / 2 ) - 3 ),
592+ (10 , 1 ),
593+ (self .height - 15 , round (self .width / 2 ) - 2 ),
617594 options = get_all_tool_category_names (),
618595 color = COLOR_FORM_BORDER ,
619596 highlight = ColorAnimation (COLOR_BUTTON .sat (0 ), COLOR_BUTTON , duration = 0.2 ),
620597 on_change = self .set_tool_category_selection ,
621598 on_select = self .set_tool_category_choice ,
622599 ),
623600 Box (
624- (11 , round (self .width / 2 )),
625- (self .height - 18 , round (self .width / 2 ) - 3 ),
601+ (10 , round (self .width / 2 ) + 1 ),
602+ (self .height - 15 , round (self .width / 2 ) - 2 ),
626603 color = COLOR_FORM_BORDER ,
627604 modules = [
628605 ASCIIText (
@@ -639,14 +616,14 @@ def form(self) -> list[Renderable]:
639616 ),
640617 WrappedText (
641618 (7 , 3 ),
642- (5 , round (self .width / 2 ) - 10 ),
619+ (min ( 5 , self . height - 24 ) , round (self .width / 2 ) - 10 ),
643620 color = COLOR_FORM .sat (50 ),
644621 value = self .tool_category_description ,
645622 ),
646623 ],
647624 ),
648625 Button (
649- (self .height - 6 , 2 ),
626+ (self .height - 5 , 2 ),
650627 (3 , 15 ),
651628 "Skip" ,
652629 color = COLOR_BUTTON ,
@@ -693,17 +670,17 @@ def back(self):
693670 def form (self ) -> list [Renderable ]:
694671 return [
695672 RadioSelect (
696- (12 , 1 ),
697- (self .height - 18 , round (self .width / 2 ) - 3 ),
673+ (10 , 1 ),
674+ (self .height - 15 , round (self .width / 2 ) - 2 ),
698675 options = self .get_tool_options (),
699676 color = COLOR_FORM_BORDER ,
700677 highlight = ColorAnimation (COLOR_BUTTON .sat (0 ), COLOR_BUTTON , duration = 0.2 ),
701678 on_change = self .set_tool_selection ,
702679 on_select = self .set_tool_choice ,
703680 ),
704681 Box (
705- (12 , round (self .width / 2 )),
706- (self .height - 18 , round (self .width / 2 ) - 3 ),
682+ (10 , round (self .width / 2 ) + 1 ),
683+ (self .height - 15 , round (self .width / 2 ) - 2 ),
707684 color = COLOR_FORM_BORDER ,
708685 modules = [
709686 ASCIIText (
@@ -715,14 +692,14 @@ def form(self) -> list[Renderable]:
715692 BoldText ((5 , 3 ), (1 , round (self .width / 2 ) - 10 ), color = COLOR_FORM , value = self .tool_name ),
716693 WrappedText (
717694 (7 , 3 ),
718- (5 , round (self .width / 2 ) - 10 ),
695+ (min ( 5 , self . height - 24 ) , round (self .width / 2 ) - 10 ),
719696 color = COLOR_FORM .sat (50 ),
720697 value = self .tool_description ,
721698 ),
722699 ],
723700 ),
724701 Button (
725- (self .height - 6 , 2 ),
702+ (self .height - 5 , 2 ),
726703 (3 , 15 ),
727704 "Back" ,
728705 color = COLOR_BUTTON ,
@@ -784,13 +761,16 @@ def submit(self):
784761 self .app .advance ()
785762
786763 def form (self ) -> list [Renderable ]:
764+ large_field_height = min (5 , round ((self .height - 17 ) / 3 ))
787765 return [
788- Text ((12 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Name" ),
789- TextInput ((12 , 13 ), (2 , self .width - 15 ), self .task_name , ** FIELD_COLORS ),
790- Text ((14 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Description" ),
791- TextInput ((14 , 13 ), (5 , self .width - 15 ), self .task_description , ** FIELD_COLORS ),
792- Text ((19 , 2 ), (1 , 11 ), color = COLOR_FORM , value = "Expected Output" ),
793- TextInput ((19 , 13 ), (5 , self .width - 15 ), self .expected_output , ** FIELD_COLORS ),
766+ Text ((11 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Name" ),
767+ TextInput ((11 , 14 ), (2 , self .width - 16 ), self .task_name , ** FIELD_COLORS ),
768+
769+ Text ((13 , 2 ), (1 , 12 ), color = COLOR_FORM , value = "Description" ),
770+ TextInput ((13 , 14 ), (large_field_height , self .width - 16 ), self .task_description , ** FIELD_COLORS ),
771+
772+ Text ((13 + large_field_height , 2 ), (2 , 12 ), color = COLOR_FORM , value = "Expected\n Output" ),
773+ TextInput ((13 + large_field_height , 14 ), (large_field_height , self .width - 16 ), self .expected_output , ** FIELD_COLORS ),
794774 ]
795775
796776
@@ -995,7 +975,7 @@ class WizardApp(App):
995975 active_view : Optional [str ]
996976
997977 min_width : int = 80
998- min_height : int = 30
978+ min_height : int = 24
999979
1000980 # the main loop can still execute once more after this; so we create an
1001981 # explicit marker to ensure the template is only written once
0 commit comments