File size: 3,835 Bytes
ad887b7
 
 
f6b1033
ad887b7
ee1878f
ad887b7
f6b1033
 
 
 
 
 
 
ad887b7
f6b1033
ad887b7
 
f6b1033
 
 
ad887b7
 
f6b1033
 
 
 
 
ad887b7
f6b1033
 
ad887b7
f6b1033
 
ee1878f
f6b1033
 
 
 
ee1878f
f6b1033
 
 
 
 
ad887b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ee1878f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ad887b7
 
 
f6b1033
ad887b7
 
f6b1033
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""Argument parsing for KnowLang CLI."""
import argparse
from pathlib import Path
from typing import Optional, Sequence, Union, Dict, Type, Callable

from knowlang.cli.commands.chat import chat_command
from knowlang.cli.commands.parse import parse_command
from knowlang.cli.types import ChatCommandArgs, ParseCommandArgs, BaseCommandArgs

# Define command configurations
COMMAND_CONFIGS: Dict[str, tuple[Type[BaseCommandArgs], Callable]] = {
    "parse": (ParseCommandArgs, parse_command),
    "chat": (ChatCommandArgs, chat_command),
}

def _convert_to_args(parsed_namespace: argparse.Namespace) -> Union[ParseCommandArgs, ChatCommandArgs]:
    """Convert parsed namespace to typed arguments."""
    base_args = {
        "verbose": parsed_namespace.verbose,
        "config": parsed_namespace.config if hasattr(parsed_namespace, "config") else None,
        "command": parsed_namespace.command
    }
    
    # Get the appropriate argument class and command function
    args_class, command_func = COMMAND_CONFIGS[parsed_namespace.command]
    
    if parsed_namespace.command == "parse":
        args = args_class(
            **base_args,
            path=Path(parsed_namespace.path).resolve(),
            output=parsed_namespace.output
        )
    elif parsed_namespace.command == "chat":
        args = args_class(
            **base_args,
            port=parsed_namespace.port,
            share=parsed_namespace.share,
            server_port=parsed_namespace.server_port,
            server_name=parsed_namespace.server_name
        )
    else:
        raise ValueError(f"Unknown command: {parsed_namespace.command}")
        
    args.command_func = command_func
    return args

def create_parser() -> argparse.ArgumentParser:
    """Create the main argument parser."""
    parser = argparse.ArgumentParser(
        description="KnowLang - Code Understanding Assistant",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    
    # Global options
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="Enable verbose output"
    )
    
    parser.add_argument(
        "--config",
        type=Path,
        help="Path to custom configuration file",
        default=None
    )
    
    # Subcommands
    subparsers = parser.add_subparsers(
        title="commands",
        description="Available commands",
        dest="command"
    )
    subparsers.required = True
    
    # Parse command
    parse_parser = subparsers.add_parser(
        "parse",
        help="Parse and index a codebase"
    )
    parse_parser.add_argument(
        "--output",
        type=str,
        choices=["table", "json"],
        default="table",
        help="Output format (default: table)"
    )
    parse_parser.add_argument(
        "path",
        type=Path,
        help="Path to codebase directory or repository URL"
    )

    # Chat command
    chat_parser = subparsers.add_parser(
        "chat",
        help="Launch the chat interface"
    )
    chat_parser.add_argument(
        "--port",
        type=int,
        help="Port to run the interface on"
    )
    chat_parser.add_argument(
        "--share",
        action="store_true",
        help="Create a shareable link"
    )
    chat_parser.add_argument(
        "--server-port",
        type=int,
        help="Port to run the server on (if different from --port)"
    )
    chat_parser.add_argument(
        "--server-name",
        type=str,
        help="Server name to listen on (default: 0.0.0.0)"
    )
    
    return parser

def parse_args(args: Optional[Sequence[str]] = None) -> Union[ParseCommandArgs, BaseCommandArgs]:
    """Parse command line arguments into typed objects."""
    parser = create_parser()
    parsed_namespace = parser.parse_args(args)
    return _convert_to_args(parsed_namespace)