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 .crud import WorkspaceCrud
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 = 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
"""
@@ -103,18 +190,60 @@ async def _activate_workspace(self, args: List[str]) -> str:
103
190
)
104
191
return f"Workspace `{ workspace_name } ` has been activated"
105
192
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 :
108
235
return (
109
236
"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>`"
111
238
)
112
239
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
115
244
116
245
updated_worksapce = await self .workspace_crud .update_workspace_system_prompt (
117
- workspace_name , sys_prompt_lst
246
+ workspace_name , args
118
247
)
119
248
if not updated_worksapce :
120
249
return (
@@ -126,37 +255,18 @@ async def _add_system_prompt(self, args: List[str]):
126
255
f"updated to:\n ```\n { updated_worksapce .system_prompt } \n ```"
127
256
)
128
257
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
-
139
258
@property
140
259
def help (self ) -> str :
141
260
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 "
145
267
"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 "
150
269
" - *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 "
162
272
)
0 commit comments