mirror of
https://github.com/Pythagora-io/gpt-pilot.git
synced 2026-01-09 21:27:53 -05:00
ask for stack before starting project and add ability to regenerate plan
This commit is contained in:
@@ -69,9 +69,10 @@ class BaseAgent:
|
||||
buttons: Optional[dict[str, str]] = None,
|
||||
default: Optional[str] = None,
|
||||
buttons_only: bool = False,
|
||||
initial_text: Optional[str] = None,
|
||||
allow_empty: bool = False,
|
||||
full_screen: Optional[bool] = False,
|
||||
hint: Optional[str] = None,
|
||||
initial_text: Optional[str] = None,
|
||||
) -> UserInput:
|
||||
"""
|
||||
Ask a question to the user and return the response.
|
||||
@@ -85,6 +86,7 @@ class BaseAgent:
|
||||
:param default: Default button to select.
|
||||
:param buttons_only: Only display buttons, no text input.
|
||||
:param allow_empty: Allow empty input.
|
||||
:param full_screen: Show question full screen in extension.
|
||||
:param hint: Text to display in a popup as a hint to the question.
|
||||
:param initial_text: Initial text input.
|
||||
:return: User response.
|
||||
@@ -95,6 +97,7 @@ class BaseAgent:
|
||||
default=default,
|
||||
buttons_only=buttons_only,
|
||||
allow_empty=allow_empty,
|
||||
full_screen=full_screen,
|
||||
hint=hint,
|
||||
initial_text=initial_text,
|
||||
source=self.ui_source,
|
||||
|
||||
@@ -12,7 +12,7 @@ from core.log import get_logger
|
||||
from core.telemetry import telemetry
|
||||
from core.templates.example_project import EXAMPLE_PROJECTS
|
||||
from core.templates.registry import PROJECT_TEMPLATES
|
||||
from core.ui.base import ProjectStage, success_source
|
||||
from core.ui.base import ProjectStage, UISource, success_source
|
||||
|
||||
log = get_logger(__name__)
|
||||
|
||||
@@ -206,12 +206,8 @@ class TechLead(BaseAgent):
|
||||
}
|
||||
for task in response.plan
|
||||
]
|
||||
await self.ui.send_epics_and_tasks(
|
||||
self.next_state.current_epic["sub_epics"],
|
||||
self.next_state.tasks,
|
||||
)
|
||||
else:
|
||||
self.next_state.current_epic["sub_epics"] = self.next_state.current_epic["sub_epics"] + [
|
||||
self.next_state.current_epic["sub_epics"] = [
|
||||
{
|
||||
"id": sub_epic_number,
|
||||
"description": sub_epic.description,
|
||||
@@ -238,11 +234,32 @@ class TechLead(BaseAgent):
|
||||
]
|
||||
convo.remove_last_x_messages(2)
|
||||
|
||||
await self.ui.send_epics_and_tasks(
|
||||
self.next_state.current_epic["sub_epics"],
|
||||
self.next_state.tasks,
|
||||
)
|
||||
await self.ui.send_message(
|
||||
"Here is the full plan:",
|
||||
source=UISource("Pythagora", "pythagora"),
|
||||
project_state_id=str(self.current_state.id),
|
||||
)
|
||||
|
||||
for sub_epic in self.next_state.current_epic["sub_epics"]:
|
||||
await self.send_message(f"Epic {sub_epic['id']}: {sub_epic['description']}")
|
||||
for task in self.next_state.tasks:
|
||||
if task["sub_epic_id"] == sub_epic["id"]:
|
||||
await self.send_message(f" - {task['description']}")
|
||||
|
||||
accept_plan = await self.ask_question(
|
||||
"Do you accept the suggested plan?",
|
||||
buttons={"yes": "Yes, the plan looks good", "regenerate": "Regenerate the plan"},
|
||||
default="yes",
|
||||
buttons_only=True,
|
||||
)
|
||||
|
||||
if accept_plan.button == "regenerate":
|
||||
return await self.plan_epic(epic)
|
||||
|
||||
await self.ui.send_epics_and_tasks(
|
||||
self.next_state.current_epic["sub_epics"],
|
||||
self.next_state.tasks,
|
||||
)
|
||||
await telemetry.trace_code_event(
|
||||
"development-plan",
|
||||
{
|
||||
|
||||
@@ -125,6 +125,40 @@ async def start_new_project(sm: StateManager, ui: UIBase) -> bool:
|
||||
:param ui: User interface.
|
||||
:return: True if the project was created successfully, False otherwise.
|
||||
"""
|
||||
|
||||
stack = await ui.ask_question(
|
||||
"What do you want to use to build your app?",
|
||||
allow_empty=False,
|
||||
buttons={"node": "Node.js", "other": "Other (coming soon)"},
|
||||
buttons_only=True,
|
||||
source=pythagora_source,
|
||||
full_screen=True,
|
||||
)
|
||||
|
||||
if stack.button == "other":
|
||||
language = await ui.ask_question(
|
||||
"What language you want to use?",
|
||||
allow_empty=False,
|
||||
source=pythagora_source,
|
||||
full_screen=True,
|
||||
)
|
||||
await telemetry.trace_code_event(
|
||||
"stack-choice-other",
|
||||
{"language": language.text},
|
||||
)
|
||||
await ui.send_message("Thank you for submitting your request to support other languages.")
|
||||
return False
|
||||
elif stack.button == "node":
|
||||
await telemetry.trace_code_event(
|
||||
"stack-choice",
|
||||
{"language": "node"},
|
||||
)
|
||||
elif stack.button == "python":
|
||||
await telemetry.trace_code_event(
|
||||
"stack-choice",
|
||||
{"language": "python"},
|
||||
)
|
||||
|
||||
while True:
|
||||
try:
|
||||
user_input = await ui.ask_question(
|
||||
|
||||
@@ -163,6 +163,7 @@ class UIBase:
|
||||
default: Optional[str] = None,
|
||||
buttons_only: bool = False,
|
||||
allow_empty: bool = False,
|
||||
full_screen: Optional[bool] = False,
|
||||
hint: Optional[str] = None,
|
||||
initial_text: Optional[str] = None,
|
||||
source: Optional[UISource] = None,
|
||||
@@ -178,11 +179,15 @@ class UIBase:
|
||||
with the selected button or text. If the user cancels
|
||||
the input, the `cancelled` attribute should be set to True.
|
||||
|
||||
:param project_state_id: Current project state id.
|
||||
:param initial_text: Placeholder for answer in extension.
|
||||
:param hint: Hint for question.
|
||||
:param question: Question to ask.
|
||||
:param buttons: Buttons to display (if any).
|
||||
:param default: Default value (if user provides no input).
|
||||
:param buttons_only: Whether to only show buttons (disallow custom text).
|
||||
:param allow_empty: Whether to allow empty input.
|
||||
:param full_screen: Ask question in full screen (IPC).
|
||||
:param source: Source of the question (if any).
|
||||
:return: User input.
|
||||
"""
|
||||
|
||||
@@ -65,6 +65,7 @@ class PlainConsoleUI(UIBase):
|
||||
default: Optional[str] = None,
|
||||
buttons_only: bool = False,
|
||||
allow_empty: bool = False,
|
||||
full_screen: Optional[bool] = False,
|
||||
hint: Optional[str] = None,
|
||||
initial_text: Optional[str] = None,
|
||||
source: Optional[UISource] = None,
|
||||
|
||||
@@ -254,6 +254,7 @@ class IPCClientUI(UIBase):
|
||||
default: Optional[str] = None,
|
||||
buttons_only: bool = False,
|
||||
allow_empty: bool = False,
|
||||
full_screen: Optional[bool] = False,
|
||||
hint: Optional[str] = None,
|
||||
initial_text: Optional[str] = None,
|
||||
source: Optional[UISource] = None,
|
||||
@@ -278,11 +279,19 @@ class IPCClientUI(UIBase):
|
||||
buttons_str = "/".join(buttons.values())
|
||||
if buttons_only:
|
||||
await self._send(
|
||||
MessageType.BUTTONS_ONLY, content=buttons_str, category=category, project_state_id=project_state_id
|
||||
MessageType.BUTTONS_ONLY,
|
||||
content=buttons_str,
|
||||
category=category,
|
||||
project_state_id=project_state_id,
|
||||
full_screen=full_screen,
|
||||
)
|
||||
else:
|
||||
await self._send(
|
||||
MessageType.BUTTONS, content=buttons_str, category=category, project_state_id=project_state_id
|
||||
MessageType.BUTTONS,
|
||||
content=buttons_str,
|
||||
category=category,
|
||||
project_state_id=project_state_id,
|
||||
full_screen=full_screen,
|
||||
)
|
||||
if initial_text:
|
||||
# FIXME: add this to base and console and document it after merging with hint PR
|
||||
|
||||
@@ -65,6 +65,7 @@ class VirtualUI(UIBase):
|
||||
default: Optional[str] = None,
|
||||
buttons_only: bool = False,
|
||||
allow_empty: bool = False,
|
||||
full_screen: Optional[bool] = False,
|
||||
hint: Optional[str] = None,
|
||||
initial_text: Optional[str] = None,
|
||||
source: Optional[UISource] = None,
|
||||
|
||||
@@ -53,6 +53,7 @@ async def test_ask_question():
|
||||
initial_text=None,
|
||||
source=agent.ui_source,
|
||||
project_state_id=str(agent.current_state.id),
|
||||
full_screen=False,
|
||||
)
|
||||
|
||||
state_manager.log_user_input.assert_awaited_once()
|
||||
|
||||
@@ -314,7 +314,7 @@ async def test_main(mock_Orchestrator, mock_llm_check, args, run_orchestrator, r
|
||||
assert success is retval
|
||||
|
||||
if run_orchestrator:
|
||||
ui.ask_question.assert_called_once()
|
||||
assert ui.ask_question.call_count == 2
|
||||
mock_Orchestrator.assert_called_once()
|
||||
mock_orca.run.assert_awaited_once_with()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user