11from abc import ABC , abstractmethod
2- from typing import List
2+ from typing import Awaitable , Callable , Dict , List , Tuple
33
44from pydantic import ValidationError
55
88from codegate .workspaces import crud
99
1010
11+ class NoFlagValueError (Exception ):
12+ pass
13+
14+ class NoSubcommandError (Exception ):
15+ pass
16+
1117class CodegateCommand (ABC ):
1218 @abstractmethod
1319 async def run (self , args : List [str ]) -> str :
1420 pass
1521
22+ @property
23+ @abstractmethod
24+ def command_name (self ) -> str :
25+ pass
26+
1627 @property
1728 @abstractmethod
1829 def help (self ) -> str :
1930 pass
2031
2132 async def exec (self , args : List [str ]) -> str :
22- if args and args [0 ] == "-h" :
33+ if len ( args ) > 0 and args [0 ] == "-h" :
2334 return self .help
2435 return await self .run (args )
2536
@@ -28,6 +39,10 @@ class Version(CodegateCommand):
2839 async def run (self , args : List [str ]) -> str :
2940 return f"CodeGate version: { __version__ } "
3041
42+ @property
43+ def command_name (self ) -> str :
44+ return "version"
45+
3146 @property
3247 def help (self ) -> str :
3348 return (
@@ -38,18 +53,90 @@ def help(self) -> str:
3853 )
3954
4055
41- class Workspace (CodegateCommand ):
56+ class CodegateCommandSubcommand (CodegateCommand ):
57+
58+ @property
59+ @abstractmethod
60+ def subcommands (self ) -> Dict [str , Callable [[List [str ]], Awaitable [str ]]]:
61+ pass
62+
63+ @property
64+ @abstractmethod
65+ def flags (self ) -> List [str ]:
66+ pass
67+
68+ def _parse_flags_and_subocomand (self , args : List [str ]) -> Tuple [Dict [str , str ], List [str ], str ]:
69+ i = 0
70+ read_flags = {}
71+ # Parse all recognized flags at the start
72+ while i < len (args ):
73+ if args [i ] in self .flags :
74+ flag_name = args [i ]
75+ if i + 1 >= len (args ):
76+ raise NoFlagValueError (f"Flag { flag_name } needs a value, but none provided." )
77+ read_flags [flag_name ] = args [i + 1 ]
78+ i += 2
79+ else :
80+ # Once we encounter something that's not a recognized flag,
81+ # we assume it's the subcommand
82+ break
83+
84+ if i >= len (args ):
85+ raise NoSubcommandError ("No subcommand found after optional flags." )
86+
87+ subcommand = args [i ]
88+ i += 1
89+
90+ # The rest of the arguments after the subcommand
91+ rest = args [i :]
92+ return read_flags , rest , subcommand
93+
94+ async def run (self , args : List [str ]) -> str :
95+ try :
96+ flags , rest , subcommand = self ._parse_flags_and_subocomand (args )
97+ except NoFlagValueError :
98+ return (
99+ f"Error reading the command. Flag without value found. "
100+ f"Use `codegate { self .command_name } -h` to see available subcommands"
101+ )
102+ except NoSubcommandError :
103+ return (
104+ f"Submmand not found "
105+ f"Use `codegate { self .command_name } -h` to see available subcommands"
106+ )
107+
108+ command_to_execute = self .subcommands .get (subcommand )
109+ if command_to_execute is None :
110+ return (
111+ f"Submmand not found "
112+ f"Use `codegate { self .command_name } -h` to see available subcommands"
113+ )
114+
115+ return await command_to_execute (flags , rest )
116+
117+
118+ class Workspace (CodegateCommandSubcommand ):
42119
43120 def __init__ (self ):
44121 self .workspace_crud = crud .WorkspaceCrud ()
45- self .commands = {
122+
123+ @property
124+ def command_name (self ) -> str :
125+ return "workspace"
126+
127+ @property
128+ def flags (self ) -> List [str ]:
129+ return []
130+
131+ @property
132+ def subcommands (self ) -> Dict [str , Callable [[List [str ]], Awaitable [str ]]]:
133+ return {
46134 "list" : self ._list_workspaces ,
47135 "add" : self ._add_workspace ,
48136 "activate" : self ._activate_workspace ,
49- "system-prompt" : self ._add_system_prompt ,
50137 }
51138
52- async def _list_workspaces (self , * args : List [str ]) -> str :
139+ async def _list_workspaces (self , flags : Dict [ str , str ], args : List [str ]) -> str :
53140 """
54141 List all workspaces
55142 """
@@ -62,7 +149,7 @@ async def _list_workspaces(self, *args: List[str]) -> str:
62149 respond_str += "\n "
63150 return respond_str
64151
65- async def _add_workspace (self , args : List [str ]) -> str :
152+ async def _add_workspace (self , flags : Dict [ str , str ], args : List [str ]) -> str :
66153 """
67154 Add a workspace
68155 """
@@ -84,7 +171,7 @@ async def _add_workspace(self, args: List[str]) -> str:
84171
85172 return f"Workspace `{ new_workspace_name } ` has been added"
86173
87- async def _activate_workspace (self , args : List [str ]) -> str :
174+ async def _activate_workspace (self , flags : Dict [ str , str ], args : List [str ]) -> str :
88175 """
89176 Activate a workspace
90177 """
@@ -105,18 +192,60 @@ async def _activate_workspace(self, args: List[str]) -> str:
105192 return "An error occurred while activating the workspace"
106193 return f"Workspace **{ workspace_name } ** has been activated"
107194
108- async def _add_system_prompt (self , args : List [str ]):
109- if len (args ) < 2 :
195+ @property
196+ def help (self ) -> str :
197+ return (
198+ "### CodeGate Workspace\n "
199+ "Manage workspaces.\n \n "
200+ "**Usage**: `codegate workspace <command> [args]`\n \n "
201+ "Available commands:\n "
202+ "- `list`: List all workspaces\n "
203+ " - *args*: None\n "
204+ " - **Usage**: `codegate workspace list`\n "
205+ "- `add`: Add a workspace\n "
206+ " - *args*:\n "
207+ " - `workspace_name`\n "
208+ " - **Usage**: `codegate workspace add <workspace_name>`\n "
209+ "- `activate`: Activate a workspace\n "
210+ " - *args*:\n "
211+ " - `workspace_name`\n "
212+ " - **Usage**: `codegate workspace activate <workspace_name>`\n "
213+ )
214+
215+
216+ class SystemPrompt (CodegateCommandSubcommand ):
217+
218+ def __init__ (self ):
219+ self .workspace_crud = crud .WorkspaceCrud ()
220+
221+ @property
222+ def command_name (self ) -> str :
223+ return "system-prompt"
224+
225+ @property
226+ def flags (self ) -> List [str ]:
227+ return ["-w" ]
228+
229+ @property
230+ def subcommands (self ) -> Dict [str , Callable [[List [str ]], Awaitable [str ]]]:
231+ return {
232+ "set" : self ._set_system_prompt ,
233+ }
234+
235+ async def _set_system_prompt (self , flags : Dict [str , str ], args : List [str ]) -> str :
236+ if len (args ) == 0 :
110237 return (
111238 "Please provide a workspace name and a system prompt. "
112- "Use `codegate workspace system-prompt <workspace_name> <system_prompt>`"
239+ "Use `codegate workspace system-prompt -w <workspace_name> <system_prompt>`"
113240 )
114241
115- workspace_name = args [0 ]
116- sys_prompt_lst = args [1 :]
242+ workspace_name = flags .get ("-w" )
243+ if not workspace_name :
244+ active_workspace = await self .workspace_crud .get_active_workspace ()
245+ workspace_name = active_workspace .name
117246
118247 updated_worksapce = await self .workspace_crud .update_workspace_system_prompt (
119- workspace_name , sys_prompt_lst
248+ workspace_name , args
120249 )
121250 if not updated_worksapce :
122251 return (
@@ -128,37 +257,18 @@ async def _add_system_prompt(self, args: List[str]):
128257 f"updated to:\n ```\n { updated_worksapce .system_prompt } \n ```"
129258 )
130259
131- async def run (self , args : List [str ]) -> str :
132- if not args :
133- return "Please provide a command. Use `codegate workspace -h` to see available commands"
134- command = args [0 ]
135- command_to_execute = self .commands .get (command )
136- if command_to_execute is not None :
137- return await command_to_execute (args [1 :])
138- else :
139- return "Command not found. Use `codegate workspace -h` to see available commands"
140-
141260 @property
142261 def help (self ) -> str :
143262 return (
144- "### CodeGate Workspace\n "
145- "Manage workspaces.\n \n "
146- "**Usage**: `codegate workspace <command> [args]`\n \n "
263+ "### CodeGate System Prompt\n "
264+ "Manage the system prompts of workspaces.\n \n "
265+ "**Usage**: `codegate system-prompt -w <workspace_name> <command>`\n \n "
266+ "*args*:\n "
267+ "- `workspace_name`: Optional workspace name. If not specified will use the "
268+ "active workspace\n \n "
147269 "Available commands:\n "
148- "- `list`: List all workspaces\n "
149- " - *args*: None\n "
150- " - **Usage**: `codegate workspace list`\n "
151- "- `add`: Add a workspace\n "
270+ "- `set`: Set the system prompt of the workspace\n "
152271 " - *args*:\n "
153- " - `workspace_name`\n "
154- " - **Usage**: `codegate workspace add <workspace_name>`\n "
155- "- `activate`: Activate a workspace\n "
156- " - *args*:\n "
157- " - `workspace_name`\n "
158- " - **Usage**: `codegate workspace activate <workspace_name>`\n "
159- "- `system-prompt`: Modify the system-prompt of a workspace\n "
160- " - *args*:\n "
161- " - `workspace_name`\n "
162- " - `system_prompt`\n "
163- " - **Usage**: `codegate workspace system-prompt <workspace_name> <system_prompt>`\n "
272+ " - `system_prompt`: The system prompt to set\n "
273+ " - **Usage**: `codegate system-prompt -w <workspace_name> set <system_prompt>`\n "
164274 )
0 commit comments