1
1
from abc import ABC , abstractmethod
2
- from typing import List
2
+ from typing import Awaitable , Callable , Dict , List , Tuple
3
3
4
4
from pydantic import ValidationError
5
5
8
8
from codegate .workspaces import crud
9
9
10
10
11
+ class NoFlagValueError (Exception ):
12
+ pass
13
+
14
+ class NoSubcommandError (Exception ):
15
+ pass
16
+
11
17
class CodegateCommand (ABC ):
12
18
@abstractmethod
13
19
async def run (self , args : List [str ]) -> str :
14
20
pass
15
21
22
+ @property
23
+ @abstractmethod
24
+ def command_name (self ) -> str :
25
+ pass
26
+
16
27
@property
17
28
@abstractmethod
18
29
def help (self ) -> str :
19
30
pass
20
31
21
32
async def exec (self , args : List [str ]) -> str :
22
- if args and args [0 ] == "-h" :
33
+ if len ( args ) > 0 and args [0 ] == "-h" :
23
34
return self .help
24
35
return await self .run (args )
25
36
@@ -28,6 +39,10 @@ class Version(CodegateCommand):
28
39
async def run (self , args : List [str ]) -> str :
29
40
return f"CodeGate version: { __version__ } "
30
41
42
+ @property
43
+ def command_name (self ) -> str :
44
+ return "version"
45
+
31
46
@property
32
47
def help (self ) -> str :
33
48
return (
@@ -38,18 +53,90 @@ def help(self) -> str:
38
53
)
39
54
40
55
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 ):
42
119
43
120
def __init__ (self ):
44
121
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 {
46
134
"list" : self ._list_workspaces ,
47
135
"add" : self ._add_workspace ,
48
136
"activate" : self ._activate_workspace ,
49
- "system-prompt" : self ._add_system_prompt ,
50
137
}
51
138
52
- async def _list_workspaces (self , * args : List [str ]) -> str :
139
+ async def _list_workspaces (self , flags : Dict [ str , str ], args : List [str ]) -> str :
53
140
"""
54
141
List all workspaces
55
142
"""
@@ -62,7 +149,7 @@ async def _list_workspaces(self, *args: List[str]) -> str:
62
149
respond_str += "\n "
63
150
return respond_str
64
151
65
- async def _add_workspace (self , args : List [str ]) -> str :
152
+ async def _add_workspace (self , flags : Dict [ str , str ], args : List [str ]) -> str :
66
153
"""
67
154
Add a workspace
68
155
"""
@@ -84,7 +171,7 @@ async def _add_workspace(self, args: List[str]) -> str:
84
171
85
172
return f"Workspace `{ new_workspace_name } ` has been added"
86
173
87
- async def _activate_workspace (self , args : List [str ]) -> str :
174
+ async def _activate_workspace (self , flags : Dict [ str , str ], args : List [str ]) -> str :
88
175
"""
89
176
Activate a workspace
90
177
"""
@@ -105,18 +192,60 @@ async def _activate_workspace(self, args: List[str]) -> str:
105
192
return "An error occurred while activating the workspace"
106
193
return f"Workspace **{ workspace_name } ** has been activated"
107
194
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 :
110
237
return (
111
238
"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>`"
113
240
)
114
241
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
117
246
118
247
updated_worksapce = await self .workspace_crud .update_workspace_system_prompt (
119
- workspace_name , sys_prompt_lst
248
+ workspace_name , args
120
249
)
121
250
if not updated_worksapce :
122
251
return (
@@ -128,37 +257,18 @@ async def _add_system_prompt(self, args: List[str]):
128
257
f"updated to:\n ```\n { updated_worksapce .system_prompt } \n ```"
129
258
)
130
259
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
-
141
260
@property
142
261
def help (self ) -> str :
143
262
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 "
147
269
"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 "
152
271
" - *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 "
164
274
)
0 commit comments