mirror of
https://github.com/Pythagora-io/gpt-pilot.git
synced 2026-01-09 13:17:55 -05:00
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,6 +8,7 @@ dist/
|
|||||||
workspace/
|
workspace/
|
||||||
pilot-env/
|
pilot-env/
|
||||||
venv/
|
venv/
|
||||||
|
data/
|
||||||
|
|
||||||
.coverage
|
.coverage
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ class SpecWriter(BaseAgent):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if user_done_with_description.button == "yes":
|
if user_done_with_description.button == "yes":
|
||||||
|
await self.ui.send_project_stage({"stage": ProjectStage.SPECS_FINISHED})
|
||||||
break
|
break
|
||||||
elif user_done_with_description.button == "no":
|
elif user_done_with_description.button == "no":
|
||||||
await self.send_message("## What would you like to add?")
|
await self.send_message("## What would you like to add?")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from core.log import get_logger
|
|||||||
from core.telemetry import telemetry
|
from core.telemetry import telemetry
|
||||||
from core.templates.registry import PROJECT_TEMPLATES
|
from core.templates.registry import PROJECT_TEMPLATES
|
||||||
from core.ui.base import ProjectStage, pythagora_source, success_source
|
from core.ui.base import ProjectStage, pythagora_source, success_source
|
||||||
|
from core.utils.text import trim_logs
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
@@ -224,8 +225,17 @@ class TechLead(RelevantFilesMixin, BaseAgent):
|
|||||||
# load the previous state, because in this state we have deleted tasks due to epic being completed!
|
# load the previous state, because in this state we have deleted tasks due to epic being completed!
|
||||||
wanted_project_state = await self.state_manager.get_project_state_by_id(self.current_state.prev_state_id)
|
wanted_project_state = await self.state_manager.get_project_state_by_id(self.current_state.prev_state_id)
|
||||||
|
|
||||||
|
wanted_project_state.epics[-1]["completed"] = False
|
||||||
self.next_state.epics = wanted_project_state.epics
|
self.next_state.epics = wanted_project_state.epics
|
||||||
|
|
||||||
|
# Trim logs from existing tasks before adding the new task
|
||||||
|
if wanted_project_state.tasks:
|
||||||
|
# Trim logs from all existing tasks
|
||||||
|
for task in wanted_project_state.tasks:
|
||||||
|
if task.get("description"):
|
||||||
|
task["description"] = trim_logs(task["description"])
|
||||||
|
|
||||||
|
# Create tasks list with new task (after trimming logs from existing tasks)
|
||||||
self.next_state.tasks = wanted_project_state.tasks + [
|
self.next_state.tasks = wanted_project_state.tasks + [
|
||||||
{
|
{
|
||||||
"id": uuid4().hex,
|
"id": uuid4().hex,
|
||||||
@@ -238,8 +248,12 @@ class TechLead(RelevantFilesMixin, BaseAgent):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Flag tasks as modified so SQLAlchemy knows to save the changes
|
||||||
|
self.next_state.flag_epics_as_modified()
|
||||||
|
self.next_state.flag_tasks_as_modified()
|
||||||
|
|
||||||
await self.ui.send_epics_and_tasks(
|
await self.ui.send_epics_and_tasks(
|
||||||
self.next_state.current_epic.get("sub_epics", []),
|
self.next_state.epics[-1].get("sub_epics", []),
|
||||||
self.next_state.tasks,
|
self.next_state.tasks,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ from core.ui.base import AgentSource, UIBase, UISource
|
|||||||
from core.ui.console import PlainConsoleUI
|
from core.ui.console import PlainConsoleUI
|
||||||
from core.ui.ipc_client import IPCClientUI
|
from core.ui.ipc_client import IPCClientUI
|
||||||
from core.ui.virtual import VirtualUI
|
from core.ui.virtual import VirtualUI
|
||||||
|
from core.utils.text import trim_logs
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
@@ -433,36 +434,6 @@ def get_epic_task_number(state, current_task) -> (int, int):
|
|||||||
return epic_num, task_num
|
return epic_num, task_num
|
||||||
|
|
||||||
|
|
||||||
def trim_logs(logs: str) -> str:
|
|
||||||
"""
|
|
||||||
Trim logs by removing everything after specific marker phrases.
|
|
||||||
|
|
||||||
This function cuts off the string at the first occurrence of
|
|
||||||
"Here are the backend logs" or "Here are the frontend logs".
|
|
||||||
|
|
||||||
:param logs: Log text to trim
|
|
||||||
:return: Trimmed log text with the marker phrase removed
|
|
||||||
"""
|
|
||||||
if not logs:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
# Define marker phrases
|
|
||||||
markers = ["Here are the backend logs", "Here are the frontend logs"]
|
|
||||||
|
|
||||||
# Find the first occurrence of any marker
|
|
||||||
index = float("inf")
|
|
||||||
for marker in markers:
|
|
||||||
pos = logs.find(marker)
|
|
||||||
if pos != -1 and pos < index:
|
|
||||||
index = pos
|
|
||||||
|
|
||||||
# If a marker was found, trim the string
|
|
||||||
if index != float("inf"):
|
|
||||||
return logs[:index]
|
|
||||||
|
|
||||||
return logs
|
|
||||||
|
|
||||||
|
|
||||||
def get_source_for_history(msg_type: Optional[str] = "", question: Optional[str] = ""):
|
def get_source_for_history(msg_type: Optional[str] = "", question: Optional[str] = ""):
|
||||||
if question in [TL_EDIT_DEV_PLAN]:
|
if question in [TL_EDIT_DEV_PLAN]:
|
||||||
return AgentSource("Tech Lead", "tech-lead")
|
return AgentSource("Tech Lead", "tech-lead")
|
||||||
|
|||||||
@@ -951,7 +951,6 @@ class ProjectState(Base):
|
|||||||
if task.get("status") == TaskStatus.SKIPPED
|
if task.get("status") == TaskStatus.SKIPPED
|
||||||
else "Done",
|
else "Done",
|
||||||
]
|
]
|
||||||
log.debug(task_histories)
|
|
||||||
|
|
||||||
last_task = {}
|
last_task = {}
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import httpx
|
|||||||
import tiktoken
|
import tiktoken
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
|
|
||||||
from core.cli.helpers import trim_logs
|
|
||||||
from core.config import LLMConfig, LLMProvider
|
from core.config import LLMConfig, LLMProvider
|
||||||
from core.llm.convo import Convo
|
from core.llm.convo import Convo
|
||||||
from core.llm.request_log import LLMRequestLog, LLMRequestStatus
|
from core.llm.request_log import LLMRequestLog, LLMRequestStatus
|
||||||
from core.log import get_logger
|
from core.log import get_logger
|
||||||
from core.state.state_manager import StateManager
|
from core.state.state_manager import StateManager
|
||||||
from core.ui.base import UIBase, pythagora_source
|
from core.ui.base import UIBase, pythagora_source
|
||||||
|
from core.utils.text import trim_logs
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
tokenizer = tiktoken.get_encoding("cl100k_base")
|
tokenizer = tiktoken.get_encoding("cl100k_base")
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from core.proc.exec_log import ExecLog as ExecLogData
|
|||||||
from core.telemetry import telemetry
|
from core.telemetry import telemetry
|
||||||
from core.ui.base import UIBase
|
from core.ui.base import UIBase
|
||||||
from core.ui.base import UserInput as UserInputData
|
from core.ui.base import UserInput as UserInputData
|
||||||
|
from core.utils.text import trim_logs
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.agents.base import BaseAgent
|
from core.agents.base import BaseAgent
|
||||||
@@ -345,6 +346,27 @@ class StateManager:
|
|||||||
await state.delete_after()
|
await state.delete_after()
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|
||||||
|
# TODO: this is a temporary fix to unblock users!
|
||||||
|
# TODO: REMOVE THIS AFTER 1 WEEK FROM THIS COMMIT
|
||||||
|
# Process tasks before setting current state - trim logs from task descriptions before current task
|
||||||
|
if state.tasks and state.current_task:
|
||||||
|
try:
|
||||||
|
# Find the current task index
|
||||||
|
current_task_index = state.tasks.index(state.current_task)
|
||||||
|
|
||||||
|
# Trim logs from all tasks before the current task
|
||||||
|
for i in range(current_task_index):
|
||||||
|
task = state.tasks[i]
|
||||||
|
if task.get("description"):
|
||||||
|
task["description"] = trim_logs(task["description"])
|
||||||
|
|
||||||
|
# Flag tasks as modified so SQLAlchemy knows to save the changes
|
||||||
|
state.flag_tasks_as_modified()
|
||||||
|
except Exception as e:
|
||||||
|
# Handle any error during log trimming gracefully
|
||||||
|
log.warning(f"Error during log trimming: {e}, skipping log trimming")
|
||||||
|
pass
|
||||||
|
|
||||||
self.current_session = session
|
self.current_session = session
|
||||||
self.current_state = state
|
self.current_state = state
|
||||||
self.branch = state.branch
|
self.branch = state.branch
|
||||||
|
|||||||
1
core/utils/__init__.py
Normal file
1
core/utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Utils module for common utility functions
|
||||||
42
core/utils/text.py
Normal file
42
core/utils/text.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
"""
|
||||||
|
Text processing utility functions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def trim_logs(logs: str) -> str:
|
||||||
|
"""
|
||||||
|
Trim logs by removing everything after specific marker phrases.
|
||||||
|
|
||||||
|
This function cuts off the string at the first occurrence of
|
||||||
|
"Here are the backend logs" or "Here are the frontend logs".
|
||||||
|
|
||||||
|
:param logs: Log text to trim
|
||||||
|
:return: Trimmed log text with the marker phrase removed
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not logs:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Ensure we have a string
|
||||||
|
if not isinstance(logs, str):
|
||||||
|
logs = str(logs)
|
||||||
|
|
||||||
|
# Define marker phrases
|
||||||
|
markers = ["Here are the backend logs", "Here are the frontend logs"]
|
||||||
|
|
||||||
|
# Find the first occurrence of any marker
|
||||||
|
index = float("inf")
|
||||||
|
for marker in markers:
|
||||||
|
pos = logs.find(marker)
|
||||||
|
if pos != -1 and pos < index:
|
||||||
|
index = pos
|
||||||
|
|
||||||
|
# If a marker was found, trim the string
|
||||||
|
if index != float("inf"):
|
||||||
|
return logs[:index]
|
||||||
|
|
||||||
|
return logs
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
# If anything goes wrong, return the original input as string or empty string
|
||||||
|
return str(logs) if logs is not None else ""
|
||||||
Reference in New Issue
Block a user