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 .crud import WorkspaceCrud
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 = 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 """
@@ -103,18 +190,60 @@ async def _activate_workspace(self, args: List[str]) -> str:
103190 )
104191 return f"Workspace `{ workspace_name } ` has been activated"
105192
106- async def _add_system_prompt (self , args : List [str ]):
107- if len (args ) < 2 :
193+ @property
194+ def help (self ) -> str :
195+ return (
196+ "### CodeGate Workspace\n "
197+ "Manage workspaces.\n \n "
198+ "**Usage**: `codegate workspace <command> [args]`\n \n "
199+ "Available commands:\n "
200+ "- `list`: List all workspaces\n "
201+ " - *args*: None\n "
202+ " - **Usage**: `codegate workspace list`\n "
203+ "- `add`: Add a workspace\n "
204+ " - *args*:\n "
205+ " - `workspace_name`\n "
206+ " - **Usage**: `codegate workspace add <workspace_name>`\n "
207+ "- `activate`: Activate a workspace\n "
208+ " - *args*:\n "
209+ " - `workspace_name`\n "
210+ " - **Usage**: `codegate workspace activate <workspace_name>`\n "
211+ )
212+
213+
214+ class SystemPrompt (CodegateCommandSubcommand ):
215+
216+ def __init__ (self ):
217+ self .workspace_crud = WorkspaceCrud ()
218+
219+ @property
220+ def command_name (self ) -> str :
221+ return "system-prompt"
222+
223+ @property
224+ def flags (self ) -> List [str ]:
225+ return ["-w" ]
226+
227+ @property
228+ def subcommands (self ) -> Dict [str , Callable [[List [str ]], Awaitable [str ]]]:
229+ return {
230+ "set" : self ._set_system_prompt ,
231+ }
232+
233+ async def _set_system_prompt (self , flags : Dict [str , str ], args : List [str ]) -> str :
234+ if len (args ) == 0 :
108235 return (
109236 "Please provide a workspace name and a system prompt. "
110- "Use `codegate workspace system-prompt <workspace_name> <system_prompt>`"
237+ "Use `codegate workspace system-prompt -w <workspace_name> <system_prompt>`"
111238 )
112239
113- workspace_name = args [0 ]
114- sys_prompt_lst = args [1 :]
240+ workspace_name = flags .get ("-w" )
241+ if not workspace_name :
242+ active_workspace = await self .workspace_crud .get_active_workspace ()
243+ workspace_name = active_workspace .name
115244
116245 updated_worksapce = await self .workspace_crud .update_workspace_system_prompt (
117- workspace_name , sys_prompt_lst
246+ workspace_name , args
118247 )
119248 if not updated_worksapce :
120249 return (
@@ -126,37 +255,18 @@ async def _add_system_prompt(self, args: List[str]):
126255 f"updated to:\n ```\n { updated_worksapce .system_prompt } \n ```"
127256 )
128257
129- async def run (self , args : List [str ]) -> str :
130- if not args :
131- return "Please provide a command. Use `codegate workspace -h` to see available commands"
132- command = args [0 ]
133- command_to_execute = self .commands .get (command )
134- if command_to_execute is not None :
135- return await command_to_execute (args [1 :])
136- else :
137- return "Command not found. Use `codegate workspace -h` to see available commands"
138-
139258 @property
140259 def help (self ) -> str :
141260 return (
142- "### CodeGate Workspace\n "
143- "Manage workspaces.\n \n "
144- "**Usage**: `codegate workspace <command> [args]`\n \n "
261+ "### CodeGate System Prompt\n "
262+ "Manage the system prompts of workspaces.\n \n "
263+ "**Usage**: `codegate system-prompt -w <workspace_name> <command>`\n \n "
264+ "*args*:\n "
265+ "- `workspace_name`: Optional workspace name. If not specified will use the "
266+ "active workspace\n \n "
145267 "Available commands:\n "
146- "- `list`: List all workspaces\n "
147- " - *args*: None\n "
148- " - **Usage**: `codegate workspace list`\n "
149- "- `add`: Add a workspace\n "
268+ "- `set`: Set the system prompt of the workspace\n "
150269 " - *args*:\n "
151- " - `workspace_name`\n "
152- " - **Usage**: `codegate workspace add <workspace_name>`\n "
153- "- `activate`: Activate a workspace\n "
154- " - *args*:\n "
155- " - `workspace_name`\n "
156- " - **Usage**: `codegate workspace activate <workspace_name>`\n "
157- "- `system-prompt`: Modify the system-prompt of a workspace\n "
158- " - *args*:\n "
159- " - `workspace_name`\n "
160- " - `system_prompt`\n "
161- " - **Usage**: `codegate workspace system-prompt <workspace_name> <system_prompt>`\n "
270+ " - `system_prompt`: The system prompt to set\n "
271+ " - **Usage**: `codegate system-prompt -w <workspace_name> set <system_prompt>`\n "
162272 )
0 commit comments