From 4ba8003e0a97a8d713d007b8a35ea0ae38a8b168 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 02:09:47 +0530 Subject: [PATCH 01/12] feat(docgen): refactor documentation generation commands and remove legacy file --- penify_hook/commands/doc_commands.py | 67 +++++++++++++++++++++++++--- penify_hook/docgen_command.py | 55 ----------------------- penify_hook/main.py | 4 +- 3 files changed, 63 insertions(+), 63 deletions(-) delete mode 100644 penify_hook/docgen_command.py diff --git a/penify_hook/commands/doc_commands.py b/penify_hook/commands/doc_commands.py index a3fafcd..36bd7dc 100644 --- a/penify_hook/commands/doc_commands.py +++ b/penify_hook/commands/doc_commands.py @@ -1,11 +1,14 @@ + +import logging import os -import sys -from ..folder_analyzer import FolderAnalyzerGenHook -from ..file_analyzer import FileAnalyzerGenHook -from ..git_analyzer import GitDocGenHook -from ..api_client import APIClient def generate_doc(api_url, token, location=None): + import os + import sys + from ..folder_analyzer import FolderAnalyzerGenHook + from ..file_analyzer import FileAnalyzerGenHook + from ..git_analyzer import GitDocGenHook + from ..api_client import APIClient """Generates documentation based on the given parameters. This function initializes an API client using the provided API URL and @@ -46,4 +49,56 @@ def generate_doc(api_url, token, location=None): analyzer.run() except Exception as e: print(f"Error: {e}") - sys.exit(1) \ No newline at end of file + sys.exit(1) + + +# Define the docgen description text +docgen_description = """Generate code documentation using Penify. + +This command requires you to be logged in to your Penify account. +You can generate documentation for: +- Current Git diff (default) +- Specific file +- Specific folder +""" + +def setup_docgen_parser(parser): + # We don't need to create a new docgen_parser since it's passed as a parameter + docgen_subparsers = parser.add_subparsers(title="docgen_subcommand", dest="docgen_subcommand") + + # Docgen main options (for direct documentation generation) + parser.add_argument("-l", "--location", help="[Optional] Path to the folder or file to Generate Documentation. By default it will pick the root directory.", default=None) + + # Subcommand: install-hook (as part of docgen) + install_hook_parser = docgen_subparsers.add_parser("install-hook", help="Install the Git post-commit hook.") + install_hook_parser.add_argument("-l", "--location", required=False, + help="Location in which to install the Git hook. Defaults to current directory.", + default=os.getcwd()) + + # Subcommand: uninstall-hook (as part of docgen) + uninstall_hook_parser = docgen_subparsers.add_parser("uninstall-hook", help="Uninstall the Git post-commit hook.") + uninstall_hook_parser.add_argument("-l", "--location", required=False, + help="Location from which to uninstall the Git hook. Defaults to current directory.", + default=os.getcwd()) + +def handle_docgen(args): + # Only import dependencies needed for docgen functionality here + from penify_hook.commands.config_commands import get_token + import sys + from penify_hook.commands.doc_commands import generate_doc + from penify_hook.commands.hook_commands import install_git_hook, uninstall_git_hook + from penify_hook.constants import API_URL + + token = get_token() + if not token: + logging.error("Error: Unable to authenticate. Please run 'penifycli login'.") + sys.exit(1) + + if args.docgen_subcommand == "install-hook": + install_git_hook(args.location, token) + + elif args.docgen_subcommand == "uninstall-hook": + uninstall_git_hook(args.location) + + else: # Direct documentation generation + generate_doc(API_URL, token, args.location) \ No newline at end of file diff --git a/penify_hook/docgen_command.py b/penify_hook/docgen_command.py deleted file mode 100644 index a638872..0000000 --- a/penify_hook/docgen_command.py +++ /dev/null @@ -1,55 +0,0 @@ -import logging -import os - - - -# Define the docgen description text -docgen_description = """Generate code documentation using Penify. - -This command requires you to be logged in to your Penify account. -You can generate documentation for: -- Current Git diff (default) -- Specific file -- Specific folder -""" - -def setup_docgen_parser(parser): - # We don't need to create a new docgen_parser since it's passed as a parameter - docgen_subparsers = parser.add_subparsers(title="docgen_subcommand", dest="docgen_subcommand") - - # Docgen main options (for direct documentation generation) - parser.add_argument("-l", "--location", help="[Optional] Path to the folder or file to Generate Documentation. By default it will pick the root directory.", default=None) - - # Subcommand: install-hook (as part of docgen) - install_hook_parser = docgen_subparsers.add_parser("install-hook", help="Install the Git post-commit hook.") - install_hook_parser.add_argument("-l", "--location", required=False, - help="Location in which to install the Git hook. Defaults to current directory.", - default=os.getcwd()) - - # Subcommand: uninstall-hook (as part of docgen) - uninstall_hook_parser = docgen_subparsers.add_parser("uninstall-hook", help="Uninstall the Git post-commit hook.") - uninstall_hook_parser.add_argument("-l", "--location", required=False, - help="Location from which to uninstall the Git hook. Defaults to current directory.", - default=os.getcwd()) - -def handle_docgen(args): - # Only import dependencies needed for docgen functionality here - from penify_hook.commands.config_commands import get_token - import sys - from penify_hook.commands.doc_commands import generate_doc - from penify_hook.commands.hook_commands import install_git_hook, uninstall_git_hook - from penify_hook.constants import API_URL - - token = get_token() - if not token: - logging.error("Error: Unable to authenticate. Please run 'penifycli login'.") - sys.exit(1) - - if args.docgen_subcommand == "install-hook": - install_git_hook(args.location, token) - - elif args.docgen_subcommand == "uninstall-hook": - uninstall_git_hook(args.location) - - else: # Direct documentation generation - generate_doc(API_URL, token, args.location) diff --git a/penify_hook/main.py b/penify_hook/main.py index 19c0750..262f877 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -38,7 +38,7 @@ def main(): setup_login_parser(login_parser) docgen_parser = subparsers.add_parser("docgen", help="[REQUIRES LOGIN] Generate code documentation for the Git diff, file or folder.") - from .docgen_command import setup_docgen_parser + from .commands.doc_commands import setup_docgen_parser setup_docgen_parser(docgen_parser) # Parse args without validation first to check for simple flags like --version @@ -65,7 +65,7 @@ def main(): from .login_command import handle_login return handle_login(args) elif args.subcommands == "docgen": - from .docgen_command import handle_docgen + from .commands.doc_commands import handle_docgen return handle_docgen(args) else: parser.print_help() From 052dfe7304d0e077a38dff61f6ac2ed6e3fcd197 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 02:14:04 +0530 Subject: [PATCH 02/12] SDG-785: refactor(commands): optimize commit handling with lazy imports ## Related JIRA Issues * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/commands/commit_commands.py | 81 ++++++++++++++++++++----- penify_hook/commit_command.py | 48 --------------- penify_hook/main.py | 4 +- 3 files changed, 68 insertions(+), 65 deletions(-) delete mode 100644 penify_hook/commit_command.py diff --git a/penify_hook/commands/commit_commands.py b/penify_hook/commands/commit_commands.py index 3c51aff..cd572b7 100644 --- a/penify_hook/commands/commit_commands.py +++ b/penify_hook/commands/commit_commands.py @@ -1,21 +1,7 @@ import os import sys +import argparse -from penify_hook.ui_utils import print_error -from penify_hook.utils import recursive_search_git_folder -from ..commit_analyzer import CommitDocGenHook -from ..api_client import APIClient - -# Try importing optional dependencies -try: - from ..llm_client import LLMClient -except ImportError: - LLMClient = None - -try: - from ..jira_client import JiraClient -except ImportError: - JiraClient = None def commit_code(api_url, token, message, open_terminal, generate_description, llm_model=None, llm_api_base=None, llm_api_key=None, @@ -23,6 +9,22 @@ def commit_code(api_url, token, message, open_terminal, generate_description, """ Enhance Git commits with AI-powered commit messages. """ + + from penify_hook.ui_utils import print_error + from penify_hook.utils import recursive_search_git_folder + from ..commit_analyzer import CommitDocGenHook + from ..api_client import APIClient + + # Try importing optional dependencies + try: + from ..llm_client import LLMClient + except ImportError: + LLMClient = None + + try: + from ..jira_client import JiraClient + except ImportError: + JiraClient = None # Create API client api_client = APIClient(api_url, token) @@ -69,3 +71,52 @@ def commit_code(api_url, token, message, open_terminal, generate_description, except Exception as e: print(f"Error: {e}") sys.exit(1) + + + + + +def setup_commit_parser(parser): + commit_parser_description = """ +It generates smart commit messages. By default, it will just generate just the Title of the commit message. +1. If you have not configured LLM, it will give an error. You either need to configure LLM or use the API key. +2. If you have not configured JIRA. It will not enhance the commit message with JIRA issue details. +3. For more information, visit https://docs.penify.dev/ +""" + parser.help = "Generate smart commit messages using local-LLM(no login required)." + parser.description = commit_parser_description + parser.formatter_class = argparse.RawDescriptionHelpFormatter + + # Add the message argument with better help + parser.add_argument("-m", "--message", required=False, help="Commit with contextual commit message.", default="N/A") + parser.add_argument("-e", "--terminal", action="store_true", help="Open edit terminal before committing.") + parser.add_argument("-d", "--description", action="store_false", help="It will generate commit message with title and description.", default=False) + +def handle_commit(args): + from penify_hook.commands.commit_commands import commit_code + from penify_hook.commands.config_commands import get_jira_config, get_llm_config, get_token + from penify_hook.constants import API_URL + + # Only import dependencies needed for commit functionality here + open_terminal = args.terminal + generate_description = args.description + print(f"Generate Description: {generate_description}") + # Try to get from config + llm_config = get_llm_config() + llm_model = llm_config.get('model') + llm_api_base = llm_config.get('api_base') + llm_api_key = llm_config.get('api_key') + token = get_token() + + + + # Try to get from config + jira_config = get_jira_config() + jira_url = jira_config.get('url') + jira_user = jira_config.get('username') + jira_api_token = jira_config.get('api_token') + + + commit_code(API_URL, token, args.message, open_terminal, generate_description, + llm_model, llm_api_base, llm_api_key, + jira_url, jira_user, jira_api_token) \ No newline at end of file diff --git a/penify_hook/commit_command.py b/penify_hook/commit_command.py deleted file mode 100644 index a04a27d..0000000 --- a/penify_hook/commit_command.py +++ /dev/null @@ -1,48 +0,0 @@ -import argparse - - - -def setup_commit_parser(parser): - commit_parser_description = """ -It generates smart commit messages. By default, it will just generate just the Title of the commit message. -1. If you have not configured LLM, it will give an error. You either need to configure LLM or use the API key. -2. If you have not configured JIRA. It will not enhance the commit message with JIRA issue details. -3. For more information, visit https://docs.penify.dev/ -""" - parser.help = "Generate smart commit messages using local-LLM(no login required)." - parser.description = commit_parser_description - parser.formatter_class = argparse.RawDescriptionHelpFormatter - - # Add the message argument with better help - parser.add_argument("-m", "--message", required=False, help="Commit with contextual commit message.", default="N/A") - parser.add_argument("-e", "--terminal", action="store_true", help="Open edit terminal before committing.") - parser.add_argument("-d", "--description", action="store_false", help="It will generate commit message with title and description.", default=False) - -def handle_commit(args): - from penify_hook.commands.commit_commands import commit_code - from penify_hook.commands.config_commands import get_jira_config, get_llm_config, get_token - from penify_hook.constants import API_URL - - # Only import dependencies needed for commit functionality here - open_terminal = args.terminal - generate_description = args.description - print(f"Generate Description: {generate_description}") - # Try to get from config - llm_config = get_llm_config() - llm_model = llm_config.get('model') - llm_api_base = llm_config.get('api_base') - llm_api_key = llm_config.get('api_key') - token = get_token() - - - - # Try to get from config - jira_config = get_jira_config() - jira_url = jira_config.get('url') - jira_user = jira_config.get('username') - jira_api_token = jira_config.get('api_token') - - - commit_code(API_URL, token, args.message, open_terminal, generate_description, - llm_model, llm_api_base, llm_api_key, - jira_url, jira_user, jira_api_token) diff --git a/penify_hook/main.py b/penify_hook/main.py index 262f877..a792bf7 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -26,7 +26,7 @@ def main(): # Set up subparsers with proper imports upfront commit_parser = subparsers.add_parser("commit", help="Generate smart commit messages using local-LLM(no login required).") - from .commit_command import setup_commit_parser + from .commands.commit_commands import setup_commit_parser setup_commit_parser(commit_parser) config_parser = subparsers.add_parser("config", help="Configure local-LLM and JIRA.") @@ -55,7 +55,7 @@ def main(): # Handle the commands if args.subcommands == "commit": print("Please wait while we generate the commit message...") - from .commit_command import handle_commit + from .commands.commit_commands import handle_commit time.sleep(1) return handle_commit(args) elif args.subcommands == "config": From ab5f5e1518a43aae97014117b5d29a2aa028b7b5 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 02:32:49 +0530 Subject: [PATCH 03/12] SDG-785: refactor(ui): enhance logging with print_info and print_warning * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/commands/commit_commands.py | 16 +++++++++------- penify_hook/commit_analyzer.py | 12 +++++++----- penify_hook/jira_client.py | 5 +++-- penify_hook/main.py | 5 +++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/penify_hook/commands/commit_commands.py b/penify_hook/commands/commit_commands.py index cd572b7..96ec297 100644 --- a/penify_hook/commands/commit_commands.py +++ b/penify_hook/commands/commit_commands.py @@ -2,6 +2,8 @@ import sys import argparse +from penify_hook.ui_utils import print_info, print_warning + def commit_code(api_url, token, message, open_terminal, generate_description, llm_model=None, llm_api_base=None, llm_api_key=None, @@ -37,10 +39,10 @@ def commit_code(api_url, token, message, open_terminal, generate_description, api_base=llm_api_base, api_key=llm_api_key ) - print(f"Using LLM model: {llm_model}") + print_info(f"Using LLM model: {llm_model}") except Exception as e: - print(f"Error initializing LLM client: {e}") - print("Falling back to API for commit summary generation") + print_error(f"Error initializing LLM client: {e}") + print_error("Falling back to API for commit summary generation") else: if not token: print_error("No LLM model or API token provided. Please provide an LLM model or API token.") @@ -55,12 +57,12 @@ def commit_code(api_url, token, message, open_terminal, generate_description, jira_api_token=jira_api_token ) if jira_client.is_connected(): - print(f"Connected to JIRA: {jira_url}") + print_info(f"Connected to JIRA: {jira_url}") else: - print(f"Failed to connect to JIRA: {jira_url}") + print_warning(f"Failed to connect to JIRA: {jira_url}") jira_client = None except Exception as e: - print(f"Error initializing JIRA client: {e}") + print_warning(f"Error initializing JIRA client: {e}") jira_client = None try: @@ -100,7 +102,7 @@ def handle_commit(args): # Only import dependencies needed for commit functionality here open_terminal = args.terminal generate_description = args.description - print(f"Generate Description: {generate_description}") + print_info(f"Generate Commit Description: {generate_description}") # Try to get from config llm_config = get_llm_config() llm_model = llm_config.get('model') diff --git a/penify_hook/commit_analyzer.py b/penify_hook/commit_analyzer.py index 65511e5..92a58a7 100644 --- a/penify_hook/commit_analyzer.py +++ b/penify_hook/commit_analyzer.py @@ -7,6 +7,7 @@ from tqdm import tqdm from penify_hook.base_analyzer import BaseAnalyzer +from penify_hook.ui_utils import print_info, print_success, print_warning from .api_client import APIClient class CommitDocGenHook(BaseAnalyzer): @@ -96,10 +97,11 @@ def run(self, msg: Optional[str], edit_commit_message: bool, generate_descriptio # commit the changes to the repository with above details commit_msg = f"{title}\n\n{description}" self.repo.git.commit('-m', commit_msg) + print_success(f"Commit: {commit_msg}") if edit_commit_message: # Open the git commit edit terminal - print("Opening git commit edit terminal...") + print_info("Opening git commit edit terminal...") self._amend_commit() def process_jira_integration(self, title: str, description: str, msg: str) -> tuple: @@ -129,12 +131,12 @@ def process_jira_integration(self, title: str, description: str, msg: str) -> tu for key in branch_issue_keys: if key not in issue_keys: issue_keys.append(key) - print(f"Added JIRA issue {key} from branch name: {current_branch}") + print_info(f"Added JIRA issue {key} from branch name: {current_branch}") except Exception as e: - print(f"Could not extract JIRA issues from branch name: {e}") + print_warning(f"Could not extract JIRA issues from branch name: {e}") if issue_keys: - print(f"Found JIRA issues: {', '.join(issue_keys)}") + print_info(f"Found JIRA issues: {', '.join(issue_keys)}") # Format commit message with JIRA info title, description = self.jira_client.format_commit_message_with_jira_info( @@ -151,7 +153,7 @@ def process_jira_integration(self, title: str, description: str, msg: str) -> tu ) self.jira_client.add_comment(issue_key, comment) else: - print("No JIRA issues found in commit message or branch name") + print_warning("No JIRA issues found in commit message or branch name") return title, description diff --git a/penify_hook/jira_client.py b/penify_hook/jira_client.py index c4f5927..67727b8 100644 --- a/penify_hook/jira_client.py +++ b/penify_hook/jira_client.py @@ -1,6 +1,8 @@ import re import logging from typing import Optional, Dict, List, Any + +from penify_hook.ui_utils import print_success try: from jira import JIRA JIRA_AVAILABLE = True @@ -69,7 +71,7 @@ def extract_issue_keys_from_branch(self, branch_name: str) -> List[str]: pattern = r'[A-Z][A-Z0-9_]+-[0-9]+' matches = re.findall(pattern, branch_name) if matches: - logging.warning(f"Found JIRA issue in branch name: {matches[0]}") + print_success(f"Found JIRA issue in branch name: {matches[0]}") return list(set(matches)) # Remove duplicates def extract_issue_keys(self, text: str) -> List[str]: @@ -85,7 +87,6 @@ def extract_issue_keys(self, text: str) -> List[str]: # Common JIRA issue key pattern: PROJECT-123 pattern = r'[A-Z][A-Z0-9_]+-[0-9]+' matches = re.findall(pattern, text) - print(f"Matches: {matches}") return list(set(matches)) # Remove duplicates def get_issue_details(self, issue_key: str) -> Optional[Dict[str, Any]]: diff --git a/penify_hook/main.py b/penify_hook/main.py index a792bf7..c05faf0 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -2,6 +2,7 @@ import sys import time + def main(): parser = argparse.ArgumentParser( description="""Penify CLI tool for: @@ -54,9 +55,9 @@ def main(): args = parser.parse_args() # Handle the commands if args.subcommands == "commit": - print("Please wait while we generate the commit message...") + from penify_hook.ui_utils import print_info + print_info("Please wait while we generate the commit message...") from .commands.commit_commands import handle_commit - time.sleep(1) return handle_commit(args) elif args.subcommands == "config": from .config_command import handle_config From dd3deafdf992c790da57b50ab9d8f81bcef4284b Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 02:49:20 +0530 Subject: [PATCH 04/12] SDG-785: Update code ## Related JIRA Issues * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/llm_client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/penify_hook/llm_client.py b/penify_hook/llm_client.py index 211d306..709092f 100644 --- a/penify_hook/llm_client.py +++ b/penify_hook/llm_client.py @@ -17,6 +17,10 @@ def __init__(self, model: str = None, api_base: str = None, api_key: str = None) api_base: Base URL for API requests (e.g., "http://localhost:11434" for Ollama) api_key: API key for the LLM service """ + print("Initializing LLM client...") + print(f"Model: {model}") + print(f"API Base: {api_base}") + print(f"API Key: {api_key}") self.model = model self.api_base = api_base self.api_key = api_key From 54a060b89f5224e3e195340102f60993fea53ee1 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:04:45 +0530 Subject: [PATCH 05/12] refactor(llm_client): configure litellm API settings directly for SDG-785 optimization ## Related JIRA Issues * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/llm_client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/penify_hook/llm_client.py b/penify_hook/llm_client.py index 709092f..db1e068 100644 --- a/penify_hook/llm_client.py +++ b/penify_hook/llm_client.py @@ -1,5 +1,6 @@ import json import os +import sys from typing import Dict, Optional, List, Any, Union import litellm @@ -24,6 +25,8 @@ def __init__(self, model: str = None, api_base: str = None, api_key: str = None) self.model = model self.api_base = api_base self.api_key = api_key + litellm.api_key = api_key + litellm.api_base = api_base # Configure litellm if parameters are provided if api_base: @@ -150,6 +153,7 @@ def generate_commit_summary(self, diff: str, message: str, generate_description: return result except Exception as e: + sys.exit(f"Error generating commit summary: {e}") # Fallback to a basic summary if LLM fails print(f"Error generating commit summary with LLM: {e}") return { From 1e4ece7ef051f458197b12d4ecdc85683c7f2a2e Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:05:53 +0530 Subject: [PATCH 06/12] SDG-785: refactor(llm_client): clean up initialization and enhance response logging This update refactors the `LLMClient` class in `llm_client.py` by removing unnecessary print statements during initialization. The API key and base URL are still set up correctly, but the initialization logs have been cleaned up for better readability. Additionally, a new print statement has been added to log the LLM response, which enhances debugging and provides better visibility into the responses received from the LLM service. ## Related JIRA Issues * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/llm_client.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/penify_hook/llm_client.py b/penify_hook/llm_client.py index db1e068..01ef0a1 100644 --- a/penify_hook/llm_client.py +++ b/penify_hook/llm_client.py @@ -17,17 +17,7 @@ def __init__(self, model: str = None, api_base: str = None, api_key: str = None) model: LLM model to use (e.g., "gpt-4", "ollama/llama2", etc.) api_base: Base URL for API requests (e.g., "http://localhost:11434" for Ollama) api_key: API key for the LLM service - """ - print("Initializing LLM client...") - print(f"Model: {model}") - print(f"API Base: {api_base}") - print(f"API Key: {api_key}") - self.model = model - self.api_base = api_base - self.api_key = api_key - litellm.api_key = api_key - litellm.api_base = api_base - + """ # Configure litellm if parameters are provided if api_base: os.environ["OPENAI_API_BASE"] = api_base @@ -121,6 +111,8 @@ def generate_commit_summary(self, diff: str, message: str, generate_description: temperature=0.2, max_tokens=800 # Increased token limit to accommodate detailed descriptions ) + + print(f"LLM response: {response}") content = response.choices[0].message.content From 21f7e643a943cd51ab571238550851b1915d3fee Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:07:09 +0530 Subject: [PATCH 07/12] SDG-785: refactor(llm-client): initialize model for lazy loading optimization ## Related JIRA Issues * **[SDG-785](https://singularity-x.atlassian.net/browse/SDG-785)**: Optimize penifycli library by using lazy lib * Status: To Do * Type: Story --- penify_hook/llm_client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/penify_hook/llm_client.py b/penify_hook/llm_client.py index 01ef0a1..d04a2ee 100644 --- a/penify_hook/llm_client.py +++ b/penify_hook/llm_client.py @@ -19,6 +19,7 @@ def __init__(self, model: str = None, api_base: str = None, api_key: str = None) api_key: API key for the LLM service """ # Configure litellm if parameters are provided + self.model = model if api_base: os.environ["OPENAI_API_BASE"] = api_base if api_key: From 22b6698856353dcbc00a8a3bbb76b5bd0530b3e3 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:09:00 +0530 Subject: [PATCH 08/12] refactor(llm_client): remove redundant logging of LLM response --- penify_hook/llm_client.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/penify_hook/llm_client.py b/penify_hook/llm_client.py index d04a2ee..fb429ba 100644 --- a/penify_hook/llm_client.py +++ b/penify_hook/llm_client.py @@ -111,10 +111,7 @@ def generate_commit_summary(self, diff: str, message: str, generate_description: messages=[{"role": "user", "content": prompt}], temperature=0.2, max_tokens=800 # Increased token limit to accommodate detailed descriptions - ) - - print(f"LLM response: {response}") - + ) content = response.choices[0].message.content # Extract JSON from the response From 28151cf99eb4a17c5b12d2b0f2464b7145cf0a0d Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:16:40 +0530 Subject: [PATCH 09/12] refactor(commit_analyzer): optimize JIRA integration and message handling --- penify_hook/commit_analyzer.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/penify_hook/commit_analyzer.py b/penify_hook/commit_analyzer.py index 92a58a7..0c9ee32 100644 --- a/penify_hook/commit_analyzer.py +++ b/penify_hook/commit_analyzer.py @@ -7,6 +7,7 @@ from tqdm import tqdm from penify_hook.base_analyzer import BaseAnalyzer +from penify_hook.jira_client import JiraClient from penify_hook.ui_utils import print_info, print_success, print_warning from .api_client import APIClient @@ -15,7 +16,7 @@ def __init__(self, repo_path: str, api_client: APIClient, llm_client=None, jira_ super().__init__(repo_path, api_client) self.llm_client = llm_client # Add LLM client as an optional parameter - self.jira_client = jira_client # Add JIRA client as an optional parameter + self.jira_client: JiraClient = jira_client # Add JIRA client as an optional parameter def get_summary(self, instruction: str, generate_description: bool) -> dict: """Generate a summary for the commit based on the staged changes. @@ -82,7 +83,7 @@ def run(self, msg: Optional[str], edit_commit_message: bool, generate_descriptio Raises: Exception: If there is an error generating the commit summary. """ - summary: dict = self.get_summary(msg, generate_description) + summary: dict = self.get_summary(msg, True) if not summary: raise Exception("Error generating commit summary") @@ -92,10 +93,10 @@ def run(self, msg: Optional[str], edit_commit_message: bool, generate_descriptio # If JIRA client is available, integrate JIRA information if self.jira_client and self.jira_client.is_connected(): # Add JIRA information to commit message - title, description = self.process_jira_integration(title, description, msg) + self.process_jira_integration(title, description, msg) # commit the changes to the repository with above details - commit_msg = f"{title}\n\n{description}" + commit_msg = f"{title}\n\n{description}" if generate_description else title self.repo.git.commit('-m', commit_msg) print_success(f"Commit: {commit_msg}") @@ -139,9 +140,6 @@ def process_jira_integration(self, title: str, description: str, msg: str) -> tu print_info(f"Found JIRA issues: {', '.join(issue_keys)}") # Format commit message with JIRA info - title, description = self.jira_client.format_commit_message_with_jira_info( - title, description, issue_keys - ) # Add comments to JIRA issues for issue_key in issue_keys: @@ -149,7 +147,6 @@ def process_jira_integration(self, title: str, description: str, msg: str) -> tu f"Commit related to this issue:\n\n" f"**{title}**\n\n" f"{description}\n\n" - f"Repository: {self.repo_details.get('organization_name')}/{self.repo_details.get('repo_name')}" ) self.jira_client.add_comment(issue_key, comment) else: From 694d0871d9722573ac09de90137adde6edd5de68 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:19:15 +0530 Subject: [PATCH 10/12] refactor(commit_analyzer, jira_client): improve logging for JIRA context retrieval --- penify_hook/commit_analyzer.py | 1 - penify_hook/jira_client.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/penify_hook/commit_analyzer.py b/penify_hook/commit_analyzer.py index 0c9ee32..d2007b5 100644 --- a/penify_hook/commit_analyzer.py +++ b/penify_hook/commit_analyzer.py @@ -52,7 +52,6 @@ def get_summary(self, instruction: str, generate_description: bool) -> dict: # If issues found in branch, get context if issue_keys: jira_context = self.jira_client.get_commit_context_from_issues(issue_keys) - print(f"Adding JIRA context from issues: {', '.join(issue_keys)}") except Exception as e: print(f"Could not get JIRA context: {e}") diff --git a/penify_hook/jira_client.py b/penify_hook/jira_client.py index 67727b8..a367405 100644 --- a/penify_hook/jira_client.py +++ b/penify_hook/jira_client.py @@ -2,7 +2,7 @@ import logging from typing import Optional, Dict, List, Any -from penify_hook.ui_utils import print_success +from penify_hook.ui_utils import print_info, print_success try: from jira import JIRA JIRA_AVAILABLE = True @@ -71,7 +71,7 @@ def extract_issue_keys_from_branch(self, branch_name: str) -> List[str]: pattern = r'[A-Z][A-Z0-9_]+-[0-9]+' matches = re.findall(pattern, branch_name) if matches: - print_success(f"Found JIRA issue in branch name: {matches[0]}") + print_info(f"Fetching relevant JIRA issues") return list(set(matches)) # Remove duplicates def extract_issue_keys(self, text: str) -> List[str]: From b8531f258a5f752d84fee1782f728e309ddc3eb6 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:47:47 +0530 Subject: [PATCH 11/12] refactor(config): centralize config path handling and update gitignore --- .gitignore | 4 ++- penify_hook/commands/config_commands.py | 45 ++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index e6b56ac..e095838 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ __pycache__/ *.pyc *.egg-info/ -build/ \ No newline at end of file +build/ +.penify/ +.penify/* diff --git a/penify_hook/commands/config_commands.py b/penify_hook/commands/config_commands.py index 8125407..77779f4 100644 --- a/penify_hook/commands/config_commands.py +++ b/penify_hook/commands/config_commands.py @@ -1,4 +1,5 @@ import json +import os import random import webbrowser import http.server @@ -8,12 +9,46 @@ from threading import Thread import logging + +def get_penify_config() -> Path: + """ + Get the home directory for the .penify configuration file. + This function searches for the .penify file in the current directory + and its parent directories until it finds it or reaches the home directory. + """ + from penify_hook.utils import recursive_search_git_folder + + current_dir = os.getcwd() + home_dir = recursive_search_git_folder(current_dir) + + + if not home_dir: + home_dir = Path.home() + else: + home_dir = Path(home_dir) + + penify_dir = home_dir / '.penify' + if penify_dir.exists(): + return penify_dir / 'config.json' + else: + # Create the .penify directory if it doesn't exist + os.makedirs(penify_dir, exist_ok=True) + ## update gitignore + + # Create the .penify directory + os.makedirs(penify_dir, exist_ok=True) + # Create an empty config.json file + with open(penify_dir / 'config.json', 'w') as f: + json.dump({}, f) + return penify_dir / 'config.json' + + def save_llm_config(model, api_base, api_key): """ Save LLM configuration settings in the .penify file. """ - home_dir = Path.home() - penify_file = home_dir / '.penify' + + penify_file = get_penify_config() config = {} if penify_file.exists(): @@ -43,6 +78,8 @@ def save_jira_config(url, username, api_token): """ Save JIRA configuration settings in the .penify file. """ + from penify_hook.utils import recursive_search_git_folder + home_dir = Path.home() penify_file = home_dir / '.penify' @@ -74,7 +111,7 @@ def get_llm_config(): """ Get LLM configuration from the .penify file. """ - config_file = Path.home() / '.penify' + config_file = get_penify_config() if config_file.exists(): try: with open(config_file, 'r') as f: @@ -89,7 +126,7 @@ def get_jira_config(): """ Get JIRA configuration from the .penify file. """ - config_file = Path.home() / '.penify' + config_file = get_penify_config() if config_file.exists(): try: with open(config_file, 'r') as f: From 072a47cb7a48e0356a6836513a20545ea1eca524 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Sat, 8 Mar 2025 03:49:22 +0530 Subject: [PATCH 12/12] refactor(commit_analyzer): add logging for LLM commit summary fetching --- penify_hook/commit_analyzer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/penify_hook/commit_analyzer.py b/penify_hook/commit_analyzer.py index d2007b5..5b89c6d 100644 --- a/penify_hook/commit_analyzer.py +++ b/penify_hook/commit_analyzer.py @@ -56,6 +56,7 @@ def get_summary(self, instruction: str, generate_description: bool) -> dict: print(f"Could not get JIRA context: {e}") # Use LLM client if provided, otherwise use API client + print_info("Fetching commit summary from LLM...") if self.llm_client: return self.api_client.generate_commit_summary_with_llm( diff, instruction, generate_description, self.repo_details, self.llm_client, jira_context