From 5ff67eee93a5edadeaf6e4f422e1340aede88b82 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 16:08:23 +0530 Subject: [PATCH 01/11] feat(commands): add login, config, commit, and docgen command handlers with argument parsing --- penify_hook/commit_command.py | 8 ++ penify_hook/config_command.py | 8 ++ penify_hook/docgen_command.py | 9 ++ penify_hook/login_command.py | 8 ++ penify_hook/main.py | 262 +++++++--------------------------- 5 files changed, 88 insertions(+), 207 deletions(-) create mode 100644 penify_hook/commit_command.py create mode 100644 penify_hook/config_command.py create mode 100644 penify_hook/docgen_command.py create mode 100644 penify_hook/login_command.py diff --git a/penify_hook/commit_command.py b/penify_hook/commit_command.py new file mode 100644 index 0000000..d0bfb0e --- /dev/null +++ b/penify_hook/commit_command.py @@ -0,0 +1,8 @@ +def setup_commit_parser(parser): + parser.add_argument("--message", "-m", help="Specify commit message directly") + # Add all other necessary arguments for commit command + +def handle_commit(args): + # Only import dependencies needed for commit functionality here + from .commit import process_commit + return process_commit(args) diff --git a/penify_hook/config_command.py b/penify_hook/config_command.py new file mode 100644 index 0000000..1934334 --- /dev/null +++ b/penify_hook/config_command.py @@ -0,0 +1,8 @@ +def setup_config_parser(parser): + parser.add_argument("--llm", help="Set the LLM provider (local or penify)") + # Add all other necessary arguments for config command + +def handle_config(args): + # Only import dependencies needed for config functionality here + from .config import process_config + return process_config(args) diff --git a/penify_hook/docgen_command.py b/penify_hook/docgen_command.py new file mode 100644 index 0000000..1deed63 --- /dev/null +++ b/penify_hook/docgen_command.py @@ -0,0 +1,9 @@ +def setup_docgen_parser(parser): + parser.add_argument("--file", "-f", help="Generate documentation for specific file") + parser.add_argument("--dir", "-d", help="Generate documentation for a directory") + # Add all other necessary arguments for docgen command + +def handle_docgen(args): + # Only import dependencies needed for docgen functionality here + from .docgen import process_docgen + return process_docgen(args) diff --git a/penify_hook/login_command.py b/penify_hook/login_command.py new file mode 100644 index 0000000..c0241dd --- /dev/null +++ b/penify_hook/login_command.py @@ -0,0 +1,8 @@ +def setup_login_parser(parser): + parser.add_argument("--token", help="Specify API token directly") + # Add all other necessary arguments for login command + +def handle_login(args): + # Only import dependencies needed for login functionality here + from .login import process_login + return process_login(args) diff --git a/penify_hook/main.py b/penify_hook/main.py index 576e06f..1a16534 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -1,221 +1,69 @@ -import os -import sys import argparse -import logging - -# Import command modules -from .commands.hook_commands import install_git_hook, uninstall_git_hook -from .commands.doc_commands import generate_doc -from .commands.commit_commands import commit_code -from .commands.auth_commands import login -from .commands.config_commands import ( - save_llm_config, save_jira_config, - config_llm_web, config_jira_web, - get_llm_config, get_jira_config, get_token -) - -# Try importing optional dependencies -try: - from .jira_client import JiraClient -except ImportError: - JiraClient = None - -# Constants -API_URL = 'https://production-gateway.snorkell.ai/api' -DASHBOARD_URL = "https://dashboard.penify.dev/auth/localhost/login" -# API_URL = 'http://localhost:8000/api' +import sys +import time def main(): - """Main entry point for the Penify CLI tool. - - This function serves as the main interface for the Penify command-line - tool, which provides various functionalities including AI commit message - generation, JIRA integration for enhancing commit messages, code - documentation generation, and Git hook installation for automatic - documentation generation. It sets up the command-line argument parser - with subcommands for basic and advanced operations. Basic commands do - not require user login, while advanced commands do. The function also - handles the parsing of arguments and the execution of the corresponding - commands based on user input. For more information about the tool and - its capabilities, please visit https://docs.penify.dev/. - """ - # Configure logging - logging.basicConfig(level=logging.WARNING, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') - - # Multi-line description using triple quotes - description = """Penify CLI tool for: -1. AI commit message generation with JIRA integration to enhance commit messages. By default, it uses local-LLM but can be configured to use Penify's LLM. + parser = argparse.ArgumentParser( + description="""Penify CLI tool for: +1. AI commit message generation with JIRA integration to enhance commit messages. 2. Generating Code Documentation, it requires SignUp to Penify -3. For more information, visit https://docs.penify.dev/ -""" +3. For more information, visit https://docs.penify.dev/""", + formatter_class=argparse.RawDescriptionHelpFormatter + ) - parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawDescriptionHelpFormatter) - # Create subparsers for the main commands - subparsers = parser.add_subparsers(title="subcommands", dest="subcommand") - - # Group commands logically - basic_title = "Basic Commands (No login required)" - advanced_title = "Advanced Commands (Login required)" - - # Create grouped subparsers (visually separated in help output) - parser.add_argument_group(basic_title) - parser.add_argument_group(advanced_title) - # ===== BASIC COMMANDS (No login required) ===== + # Add version flag + parser.add_argument('--version', '-v', action='store_true', help='Show version information') + subparsers = parser.add_subparsers(title="subcommands", dest="command") - 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/ -""" - - # Subcommand: commit - commit_parser = subparsers.add_parser("commit", help="Generate smart commit messages using local-LLM(no login required).", description=commit_parser_description, formatter_class=argparse.RawDescriptionHelpFormatter) - commit_parser.add_argument("-m", "--message", required=False, help="Commit with contextual commit message.", default="N/A") - commit_parser.add_argument("-e", "--terminal", action="store_true", help="Open edit terminal before committing.") - commit_parser.add_argument("-d", "--description", action="store_false", help="It will generate commit message with title and description.", default=False) - - # Subcommand: config + # Define subparsers without importing their modules yet + commit_parser = subparsers.add_parser("commit", help="Generate smart commit messages using local-LLM(no login required).") config_parser = subparsers.add_parser("config", help="Configure local-LLM and JIRA.") - config_subparsers = config_parser.add_subparsers(title="config_type", dest="config_type") - - # Config subcommand: llm - llm_config_parser = config_subparsers.add_parser("llm", help="Configure LLM settings.") - llm_config_parser.add_argument("--model", required=True, help="LLM model to use") - llm_config_parser.add_argument("--api-base", help="API base URL for the LLM service") - llm_config_parser.add_argument("--api-key", help="API key for the LLM service") - - # Config subcommand: llm-web - config_subparsers.add_parser("llm-web", help="Configure LLM settings through a web interface") - - # Config subcommand: jira - jira_config_parser = config_subparsers.add_parser("jira", help="Configure JIRA settings.") - jira_config_parser.add_argument("--url", required=True, help="JIRA base URL") - jira_config_parser.add_argument("--username", required=True, help="JIRA username or email") - jira_config_parser.add_argument("--api-token", required=True, help="JIRA API token") - jira_config_parser.add_argument("--verify", action="store_true", help="Verify JIRA connection") - - # Config subcommand: jira-web - config_subparsers.add_parser("jira-web", help="Configure JIRA settings through a web interface") - - # ===== ADVANCED COMMANDS (Login required) ===== - - # Subcommand: login (bridge between basic and advanced) login_parser = subparsers.add_parser("login", help="Log in to Penify to use advanced features like 'docgen' generation.") - - docgen_description="""By default, 'docgen' generates documentation for the latest Git commit diff. Use the -l flag to document a specific file or folder. - -The 'install-hook' command sets up a Git post-commit hook to auto-generate documentation after each commit. -""" - - # Advanced Subcommand: docgen - docgen_parser = subparsers.add_parser("docgen", help="[REQUIRES LOGIN] Generate code documentation for the Git diff, file or folder.", description=docgen_description, formatter_class=argparse.RawDescriptionHelpFormatter) - docgen_subparsers = docgen_parser.add_subparsers(title="docgen_subcommand", dest="docgen_subcommand") - - # Docgen main options (for direct documentation generation) - docgen_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()) - - args = parser.parse_args() - - # Get the token based on priority - token = get_token() - - # Process commands - if args.subcommand == "docgen": - # Check for login for all advanced commands - 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) - - elif args.subcommand == "commit": - # For commit, token is now optional - some functionality may be limited without it - 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') - - - - # 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) - - elif args.subcommand == "config": - # Config doesn't require token - if args.config_type == "llm": - save_llm_config(args.model, args.api_base, args.api_key) - print(f"LLM configuration set: Model={args.model}, API Base={args.api_base or 'default'}") - - elif args.config_type == "llm-web": - config_llm_web() - - elif args.config_type == "jira": - save_jira_config(args.url, args.username, args.api_token) - print(f"JIRA configuration set: URL={args.url}, Username={args.username}") - - # Verify connection if requested - if args.verify: - if JiraClient: - jira_client = JiraClient( - jira_url=args.url, - jira_user=args.username, - jira_api_token=args.api_token - ) - if jira_client.is_connected(): - print("JIRA connection verified successfully!") - else: - print("Failed to connect to JIRA. Please check your credentials.") - else: - print("JIRA package not installed. Cannot verify connection.") - - elif args.config_type == "jira-web": - config_jira_web() - - else: - config_parser.print_help() - - elif args.subcommand == "login": - login(API_URL, DASHBOARD_URL) - + docgen_parser = subparsers.add_parser("docgen", help="[REQUIRES LOGIN] Generate code documentation for the Git diff, file or folder.") + + # Parse args without validation first to check for simple flags like --version + if '--version' in sys.argv or '-v' in sys.argv: + from importlib.metadata import version + try: + print(f"penifycli version {version('penifycli')}") + except: + print("penifycli version 0.2.2") + return 0 + + print("Welcome to Penify CLI!") + + # Parse the arguments to determine which command was requested + args, unknown = parser.parse_known_args() + # print(f"Unknown args: {unknown}") + # print(f"Running command: {args.command}") + print("Please run 'penifycli --help' to see the available commands.") + + + # Import only the needed module based on the command + if args.command == "commit": + print("Please wait while we generate the commit message...") + from .commit_command import setup_commit_parser, handle_commit + setup_commit_parser(commit_parser) + time.sleep(1) + sys.exit(0) + return handle_commit(parser.parse_args()) + elif args.command == "config": + from .config_command import setup_config_parser, handle_config + setup_config_parser(config_parser) + return handle_config(parser.parse_args()) + elif args.command == "login": + from .login_command import setup_login_parser, handle_login + setup_login_parser(login_parser) + return handle_login(parser.parse_args()) + elif args.command == "docgen": + from .docgen_command import setup_docgen_parser, handle_docgen + setup_docgen_parser(docgen_parser) + return handle_docgen(parser.parse_args()) else: parser.print_help() - sys.exit(1) + return 1 if __name__ == "__main__": - main() + sys.exit(main()) From 0df68a70dff972b91c1b6fdc446aa8c094a9321d Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 17:53:15 +0530 Subject: [PATCH 02/11] feat(commit): enhance commit message generation with LLM and JIRA --- penify_hook/commit_command.py | 48 ++++++++++++++++++++++++++++--- penify_hook/constants.py | 2 ++ penify_hook/main.py | 53 ++++++++++++++++++++--------------- 3 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 penify_hook/constants.py diff --git a/penify_hook/commit_command.py b/penify_hook/commit_command.py index d0bfb0e..a04a27d 100644 --- a/penify_hook/commit_command.py +++ b/penify_hook/commit_command.py @@ -1,8 +1,48 @@ +import argparse + + + def setup_commit_parser(parser): - parser.add_argument("--message", "-m", help="Specify commit message directly") - # Add all other necessary arguments for commit command + 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 - from .commit import process_commit - return process_commit(args) + 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/constants.py b/penify_hook/constants.py new file mode 100644 index 0000000..631c61b --- /dev/null +++ b/penify_hook/constants.py @@ -0,0 +1,2 @@ +API_URL = 'https://production-gateway.snorkell.ai/api' +DASHBOARD_URL = "https://dashboard.penify.dev/auth/localhost/login" \ No newline at end of file diff --git a/penify_hook/main.py b/penify_hook/main.py index 1a16534..c088f1c 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -11,17 +11,35 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter ) - # Add version flag parser.add_argument('--version', '-v', action='store_true', help='Show version information') - subparsers = parser.add_subparsers(title="subcommands", dest="command") + subparsers = parser.add_subparsers(title="options", dest="subcommands") + + # Group commands logically + basic_title = "Basic Commands (No login required)" + advanced_title = "Advanced Commands (Login required)" + + # Create grouped subparsers (visually separated in help output) + parser.add_argument_group(basic_title) + parser.add_argument_group(advanced_title) - # Define subparsers without importing their modules yet + # 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 + setup_commit_parser(commit_parser) + config_parser = subparsers.add_parser("config", help="Configure local-LLM and JIRA.") + from .config_command import setup_config_parser + setup_config_parser(config_parser) + login_parser = subparsers.add_parser("login", help="Log in to Penify to use advanced features like 'docgen' generation.") + from .login_command import setup_login_parser + 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 + setup_docgen_parser(docgen_parser) # Parse args without validation first to check for simple flags like --version if '--version' in sys.argv or '-v' in sys.argv: @@ -35,32 +53,23 @@ def main(): print("Welcome to Penify CLI!") # Parse the arguments to determine which command was requested - args, unknown = parser.parse_known_args() - # print(f"Unknown args: {unknown}") - # print(f"Running command: {args.command}") - print("Please run 'penifycli --help' to see the available commands.") - + args = parser.parse_args() - # Import only the needed module based on the command + # Handle the commands if args.command == "commit": print("Please wait while we generate the commit message...") - from .commit_command import setup_commit_parser, handle_commit - setup_commit_parser(commit_parser) + from .commit_command import handle_commit time.sleep(1) - sys.exit(0) - return handle_commit(parser.parse_args()) + return handle_commit(args) elif args.command == "config": - from .config_command import setup_config_parser, handle_config - setup_config_parser(config_parser) - return handle_config(parser.parse_args()) + from .config_command import handle_config + return handle_config(args) elif args.command == "login": - from .login_command import setup_login_parser, handle_login - setup_login_parser(login_parser) - return handle_login(parser.parse_args()) + from .login_command import handle_login + return handle_login(args) elif args.command == "docgen": - from .docgen_command import setup_docgen_parser, handle_docgen - setup_docgen_parser(docgen_parser) - return handle_docgen(parser.parse_args()) + from .docgen_command import handle_docgen + return handle_docgen(args) else: parser.print_help() return 1 From 75d3bb63893018ca1c6e6c2bca5b91caf36b7138 Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 17:54:15 +0530 Subject: [PATCH 03/11] fix(main): update command handling to use subcommands instead of commands --- penify_hook/main.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/penify_hook/main.py b/penify_hook/main.py index c088f1c..bd4fb6a 100644 --- a/penify_hook/main.py +++ b/penify_hook/main.py @@ -53,21 +53,20 @@ def main(): print("Welcome to Penify CLI!") # Parse the arguments to determine which command was requested - args = parser.parse_args() - + args = parser.parse_args() # Handle the commands - if args.command == "commit": + if args.subcommands == "commit": print("Please wait while we generate the commit message...") from .commit_command import handle_commit time.sleep(1) return handle_commit(args) - elif args.command == "config": + elif args.subcommands == "config": from .config_command import handle_config return handle_config(args) - elif args.command == "login": + elif args.subcommands == "login": from .login_command import handle_login return handle_login(args) - elif args.command == "docgen": + elif args.subcommands == "docgen": from .docgen_command import handle_docgen return handle_docgen(args) else: From 76c4c87369e06237a4dc758effe8cf00bb29d6be Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 18:04:25 +0530 Subject: [PATCH 04/11] feat(config): implement subcommands for LLM and JIRA configuration with argument parsing --- penify_hook/config_command.py | 64 ++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/penify_hook/config_command.py b/penify_hook/config_command.py index 1934334..ed6c3e9 100644 --- a/penify_hook/config_command.py +++ b/penify_hook/config_command.py @@ -1,8 +1,64 @@ -def setup_config_parser(parser): - parser.add_argument("--llm", help="Set the LLM provider (local or penify)") + + +from penify_hook.commands.config_commands import config_jira_web, config_llm_web, save_jira_config +from penify_hook.jira_client import JiraClient + + +def setup_config_parser(parent_parser): + # Config subcommand: llm + parser = parent_parser.add_subparsers(title="config_type", dest="config_type") + + llm_config_parser = parser.add_subparsers("llm", help="Configure LLM settings.") + llm_config_parser.add_argument("--model", required=True, help="LLM model to use") + llm_config_parser.add_argument("--api-base", help="API base URL for the LLM service") + llm_config_parser.add_argument("--api-key", help="API key for the LLM service") + + parser.add_parser("llm-web", help="Configure LLM settings through a web interface") + + # Config subcommand: jira + jira_config_parser = parser.add_parser("jira", help="Configure JIRA settings.") + jira_config_parser.add_argument("--url", required=True, help="JIRA base URL") + jira_config_parser.add_argument("--username", required=True, help="JIRA username or email") + jira_config_parser.add_argument("--api-token", required=True, help="JIRA API token") + jira_config_parser.add_argument("--verify", action="store_true", help="Verify JIRA connection") + + # Config subcommand: jira-web + parser.add_parser("jira-web", help="Configure JIRA settings through a web interface") + # Add all other necessary arguments for config command def handle_config(args): # Only import dependencies needed for config functionality here - from .config import process_config - return process_config(args) + from penify_hook.commands.config_commands import save_llm_config + + if args.config_type == "llm": + save_llm_config(args.model, args.api_base, args.api_key) + print(f"LLM configuration set: Model={args.model}, API Base={args.api_base or 'default'}") + + elif args.config_type == "llm-web": + config_llm_web() + + elif args.config_type == "jira": + save_jira_config(args.url, args.username, args.api_token) + print(f"JIRA configuration set: URL={args.url}, Username={args.username}") + + # Verify connection if requested + if args.verify: + if JiraClient: + jira_client = JiraClient( + jira_url=args.url, + jira_user=args.username, + jira_api_token=args.api_token + ) + if jira_client.is_connected(): + print("JIRA connection verified successfully!") + else: + print("Failed to connect to JIRA. Please check your credentials.") + else: + print("JIRA package not installed. Cannot verify connection.") + + elif args.config_type == "jira-web": + config_jira_web() + + else: + config_parser.print_help() From 612aaa9564dcae09284b3e5a74ee49fe7ec1303c Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 18:06:59 +0530 Subject: [PATCH 05/11] feat(config): refine config command parser and improve error handling --- penify_hook/config_command.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/penify_hook/config_command.py b/penify_hook/config_command.py index ed6c3e9..4c525bb 100644 --- a/penify_hook/config_command.py +++ b/penify_hook/config_command.py @@ -1,18 +1,17 @@ - - from penify_hook.commands.config_commands import config_jira_web, config_llm_web, save_jira_config -from penify_hook.jira_client import JiraClient def setup_config_parser(parent_parser): - # Config subcommand: llm + # Config subcommand: Create subparsers for config types parser = parent_parser.add_subparsers(title="config_type", dest="config_type") - llm_config_parser = parser.add_subparsers("llm", help="Configure LLM settings.") + # Config subcommand: llm + llm_config_parser = parser.add_parser("llm", help="Configure LLM settings.") llm_config_parser.add_argument("--model", required=True, help="LLM model to use") llm_config_parser.add_argument("--api-base", help="API base URL for the LLM service") llm_config_parser.add_argument("--api-key", help="API key for the LLM service") + # Config subcommand: llm-web parser.add_parser("llm-web", help="Configure LLM settings through a web interface") # Config subcommand: jira @@ -30,6 +29,7 @@ def setup_config_parser(parent_parser): def handle_config(args): # Only import dependencies needed for config functionality here from penify_hook.commands.config_commands import save_llm_config + from penify_hook.jira_client import JiraClient # Import moved here if args.config_type == "llm": save_llm_config(args.model, args.api_base, args.api_key) @@ -61,4 +61,7 @@ def handle_config(args): config_jira_web() else: - config_parser.print_help() + print("Please specify a config type: llm, llm-web, jira, or jira-web") + return 1 + + return 0 From c49e0c75295226e7e432d3102e9b0c5a8253d68f Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 18:09:18 +0530 Subject: [PATCH 06/11] fix(config): reorder imports for config command functionality --- penify_hook/config_command.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/penify_hook/config_command.py b/penify_hook/config_command.py index 4c525bb..6f76894 100644 --- a/penify_hook/config_command.py +++ b/penify_hook/config_command.py @@ -1,4 +1,4 @@ -from penify_hook.commands.config_commands import config_jira_web, config_llm_web, save_jira_config + def setup_config_parser(parent_parser): @@ -30,6 +30,7 @@ def handle_config(args): # Only import dependencies needed for config functionality here from penify_hook.commands.config_commands import save_llm_config from penify_hook.jira_client import JiraClient # Import moved here + from penify_hook.commands.config_commands import config_jira_web, config_llm_web, save_jira_config if args.config_type == "llm": save_llm_config(args.model, args.api_base, args.api_key) From 20755b1d8b774f00f4e562fc8c037ccbd5c5298a Mon Sep 17 00:00:00 2001 From: sumansaurabh Date: Fri, 7 Mar 2025 20:16:15 +0530 Subject: [PATCH 07/11] feat(config): add endpoint to retrieve current LLM configuration and enhance UI for displaying settings --- penify_hook/commands/config_commands.py | 20 ++++++ penify_hook/templates/llm_config.html | 85 ++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/penify_hook/commands/config_commands.py b/penify_hook/commands/config_commands.py index 19b1c35..ec72985 100644 --- a/penify_hook/commands/config_commands.py +++ b/penify_hook/commands/config_commands.py @@ -125,6 +125,26 @@ def do_GET(self): content = f.read() self.wfile.write(content.encode()) + elif self.path == "/get_config": + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + + # Get current LLM configuration + current_config = get_llm_config() + + if current_config: + response = { + "success": True, + "config": current_config + } + else: + response = { + "success": False, + "message": "No configuration found" + } + + self.wfile.write(json.dumps(response).encode()) else: self.send_response(404) self.send_header("Content-type", "text/plain") diff --git a/penify_hook/templates/llm_config.html b/penify_hook/templates/llm_config.html index 810fa7e..7806a6a 100644 --- a/penify_hook/templates/llm_config.html +++ b/penify_hook/templates/llm_config.html @@ -30,7 +30,8 @@ margin-bottom: 8px; font-weight: bold; } - input[type="text"] { + input[type="text"], + input[type="password"] { width: 100%; padding: 10px; border: 1px solid #ddd; @@ -83,6 +84,29 @@ background-color: #f1f3f5; border-color: #adb5bd; } + .input-group { + position: relative; + } + .toggle-password { + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + cursor: pointer; + user-select: none; + font-size: 14px; + color: #666; + background: none; + border: none; + padding: 0; + } + .current-config { + background-color: #e0f7fa; + padding: 10px 15px; + border-radius: 4px; + margin-bottom: 20px; + border-left: 4px solid #0066cc; + } @@ -90,6 +114,11 @@

LLM Configuration

Configure your preferred LLM (Large Language Model) for generating commit messages.

+
+

Current Configuration

+
Loading current settings...
+
+
@@ -105,7 +134,10 @@

LLM Configuration

- +
+ + +

Required for commercial LLMs like OpenAI's GPT models

@@ -125,6 +157,55 @@

Quick Config Presets: