2025-11-04 05:17:27 +01:00
|
|
|
import argparse
|
|
|
|
|
import sys
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
from pr import __version__
|
2025-11-04 08:09:12 +01:00
|
|
|
from pr.core import Assistant
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
parser = argparse.ArgumentParser(
|
2025-11-04 08:09:12 +01:00
|
|
|
description="PR Assistant - Professional CLI AI assistant with autonomous execution",
|
|
|
|
|
epilog="""
|
2025-11-04 05:17:27 +01:00
|
|
|
Examples:
|
|
|
|
|
pr "What is Python?" # Single query
|
|
|
|
|
pr -i # Interactive mode
|
|
|
|
|
pr -i --model gpt-4 # Use specific model
|
|
|
|
|
pr --save-session my-task -i # Save session
|
|
|
|
|
pr --load-session my-task # Load session
|
|
|
|
|
pr --list-sessions # List all sessions
|
|
|
|
|
pr --usage # Show token usage stats
|
|
|
|
|
|
|
|
|
|
Commands in interactive mode:
|
|
|
|
|
/auto [task] - Enter autonomous mode
|
|
|
|
|
/reset - Clear message history
|
|
|
|
|
/verbose - Toggle verbose output
|
|
|
|
|
/models - List available models
|
|
|
|
|
/tools - List available tools
|
|
|
|
|
/usage - Show usage statistics
|
|
|
|
|
/save <name> - Save current session
|
|
|
|
|
exit, quit, q - Exit the program
|
2025-11-04 08:09:12 +01:00
|
|
|
""",
|
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parser.add_argument("message", nargs="?", help="Message to send to assistant")
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("--version", action="version", version=f"PR Assistant {__version__}")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument("-m", "--model", help="AI model to use")
|
|
|
|
|
parser.add_argument("-u", "--api-url", help="API endpoint URL")
|
|
|
|
|
parser.add_argument("--model-list-url", help="Model list endpoint URL")
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("-i", "--interactive", action="store_true", help="Interactive mode")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--debug", action="store_true", help="Enable debug mode with detailed logging"
|
|
|
|
|
)
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("--no-syntax", action="store_true", help="Disable syntax highlighting")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--include-env",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Include environment variables in context",
|
|
|
|
|
)
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("-c", "--context", action="append", help="Additional context files")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--api-mode", action="store_true", help="API mode for specialized interaction"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--output",
|
|
|
|
|
choices=["text", "json", "structured"],
|
|
|
|
|
default="text",
|
|
|
|
|
help="Output format",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument("--quiet", action="store_true", help="Minimal output")
|
|
|
|
|
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("--save-session", metavar="NAME", help="Save session with given name")
|
|
|
|
|
parser.add_argument("--load-session", metavar="NAME", help="Load session with given name")
|
|
|
|
|
parser.add_argument("--list-sessions", action="store_true", help="List all saved sessions")
|
|
|
|
|
parser.add_argument("--delete-session", metavar="NAME", help="Delete a saved session")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--export-session",
|
|
|
|
|
nargs=2,
|
|
|
|
|
metavar=("NAME", "FILE"),
|
|
|
|
|
help="Export session to file",
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-04 08:10:37 +01:00
|
|
|
parser.add_argument("--usage", action="store_true", help="Show token usage statistics")
|
2025-11-04 08:09:12 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--create-config", action="store_true", help="Create default configuration file"
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument("--plugins", action="store_true", help="List loaded plugins")
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if args.create_config:
|
|
|
|
|
from pr.core.config_loader import create_default_config
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
if create_default_config():
|
|
|
|
|
print("Configuration file created at ~/.prrc")
|
|
|
|
|
else:
|
|
|
|
|
print("Error creating configuration file", file=sys.stderr)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if args.list_sessions:
|
|
|
|
|
from pr.core.session import SessionManager
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
sm = SessionManager()
|
|
|
|
|
sessions = sm.list_sessions()
|
|
|
|
|
if not sessions:
|
|
|
|
|
print("No saved sessions found")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Found {len(sessions)} saved sessions:\n")
|
|
|
|
|
for sess in sessions:
|
|
|
|
|
print(f" {sess['name']}")
|
|
|
|
|
print(f" Created: {sess['created_at']}")
|
|
|
|
|
print(f" Messages: {sess['message_count']}")
|
|
|
|
|
print()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if args.delete_session:
|
|
|
|
|
from pr.core.session import SessionManager
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
sm = SessionManager()
|
|
|
|
|
if sm.delete_session(args.delete_session):
|
|
|
|
|
print(f"Session '{args.delete_session}' deleted")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Error deleting session '{args.delete_session}'", file=sys.stderr)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if args.export_session:
|
|
|
|
|
from pr.core.session import SessionManager
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
sm = SessionManager()
|
|
|
|
|
name, output_file = args.export_session
|
2025-11-04 08:09:12 +01:00
|
|
|
format_type = "json"
|
|
|
|
|
if output_file.endswith(".md"):
|
|
|
|
|
format_type = "markdown"
|
|
|
|
|
elif output_file.endswith(".txt"):
|
|
|
|
|
format_type = "txt"
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
if sm.export_session(name, output_file, format_type):
|
|
|
|
|
print(f"Session exported to {output_file}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Error exporting session", file=sys.stderr)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if args.usage:
|
|
|
|
|
from pr.core.usage_tracker import UsageTracker
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
usage = UsageTracker.get_total_usage()
|
|
|
|
|
print(f"\nTotal Usage Statistics:")
|
|
|
|
|
print(f" Requests: {usage['total_requests']}")
|
|
|
|
|
print(f" Tokens: {usage['total_tokens']:,}")
|
|
|
|
|
print(f" Estimated Cost: ${usage['total_cost']:.4f}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if args.plugins:
|
|
|
|
|
from pr.plugins.loader import PluginLoader
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
loader = PluginLoader()
|
|
|
|
|
loader.load_plugins()
|
|
|
|
|
plugins = loader.list_loaded_plugins()
|
|
|
|
|
if not plugins:
|
|
|
|
|
print("No plugins loaded")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Loaded {len(plugins)} plugins:")
|
|
|
|
|
for plugin in plugins:
|
|
|
|
|
print(f" - {plugin}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
assistant = Assistant(args)
|
|
|
|
|
assistant.run()
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-11-04 05:17:27 +01:00
|
|
|
main()
|