Skip to content

Commit c11cb59

Browse files
committed
Renders ad 80x24
1 parent b37e483 commit c11cb59

File tree

2 files changed

+105
-113
lines changed

2 files changed

+105
-113
lines changed

agentstack/cli/wizard.py

Lines changed: 81 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
COLOR_BORDER = Color(90)
2828
COLOR_MAIN = Color(220)
2929
COLOR_TITLE = Color(220, 100, 40, reversed=True)
30-
COLOR_ERROR = Color(0, 50)
30+
COLOR_ERROR = Color(0, 70)
3131
COLOR_BANNER = Color(80, 80, 80)
3232
COLOR_FORM = Color(300)
3333
COLOR_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\nOutput"),
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

Comments
 (0)