diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 38b532ef..2b5e4e71 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -75,20 +75,45 @@ class GitProvider(ABC): def get_user_description(self) -> str: description = (self.get_pr_description_full() or "").strip() description_lowercase = description.lower() + # if the existing description wasn't generated by the pr-agent, just return it as-is if not self._is_generated_by_pr_agent(description_lowercase): return description - # if the existing description was generated by the pr-agent, but it doesn't contain the user description, + + # if the existing description was generated by the pr-agent, but it doesn't contain a user description, # return nothing (empty string) because it means there is no user description user_description_header = "## user description" if user_description_header not in description_lowercase: return "" + # otherwise, extract the original user description from the existing pr-agent description and return it - user_description_start_position = description_lowercase.find(user_description_header) + len(user_description_header) - return description[user_description_start_position:].split("\n", 1)[-1].strip() + # user_description_start_position = description_lowercase.find(user_description_header) + len(user_description_header) + # return description[user_description_start_position:].split("\n", 1)[-1].strip() + + # the 'user description' is in the beginning. extract and return it + possible_headers = self._possible_headers() + start_position = description_lowercase.find(user_description_header) + len(user_description_header) + end_position = len(description) + for header in possible_headers: # try to clip at the next header + if header != user_description_header and header in description_lowercase: + end_position = min(end_position, description_lowercase.find(header)) + if end_position != len(description) and end_position > start_position: + original_user_description = description[start_position:end_position].strip() + if original_user_description.endswith("___"): + original_user_description = original_user_description[:-3].strip() + else: + original_user_description = description.split("___")[0].strip() + if original_user_description.lower().startswith(user_description_header): + original_user_description = original_user_description[len(user_description_header):].strip() + + return original_user_description + + def _possible_headers(self): + return ("## user description", "## pr type", "## pr description", "## pr labels", "## type", "## description", + "## labels", "### 🤖 generated by pr agent") def _is_generated_by_pr_agent(self, description_lowercase: str) -> bool: - possible_headers = ("## pr type", "## pr description", "## pr labels", "## type", "## description", "## labels", "### 🤖 generated by pr agent") + possible_headers = self._possible_headers() return any(description_lowercase.startswith(header) for header in possible_headers) @abstractmethod diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 362849d5..858b8921 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -185,7 +185,12 @@ class PRDescription: # Load the AI prediction data into a dictionary self.data = load_yaml(self.prediction.strip()) + if get_settings().pr_description.add_original_user_description and self.user_description: + self.data["User Description"] = self.user_description + # re-order keys + if 'User Description' in self.data: + self.data['User Description'] = self.data.pop('User Description') if 'title' in self.data: self.data['title'] = self.data.pop('title') if 'type' in self.data: @@ -197,8 +202,7 @@ class PRDescription: if 'pr_files' in self.data: self.data['pr_files'] = self.data.pop('pr_files') - if get_settings().pr_description.add_original_user_description and self.user_description: - self.data["User Description"] = self.user_description + def _prepare_labels(self) -> List[str]: