Skip to content

Commit d82ee68

Browse files
separated into it's own command system-prompt
1 parent b6f255c commit d82ee68

File tree

3 files changed

+155
-45
lines changed

3 files changed

+155
-45
lines changed

src/codegate/db/connection.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,7 @@ async def add_workspace(self, workspace_name: str) -> Optional[Workspace]:
256256
It may raise a ValidationError if the workspace name is invalid.
257257
or a AlreadyExistsError if the workspace already exists.
258258
"""
259-
workspace = Workspace(id=str(uuid.uuid4()), name=workspace_name)
260-
259+
workspace = Workspace(id=str(uuid.uuid4()), name=workspace_name, system_prompt=None)
261260
sql = text(
262261
"""
263262
INSERT INTO workspaces (id, name)

src/codegate/pipeline/cli/cli.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
PipelineResult,
99
PipelineStep,
1010
)
11-
from codegate.pipeline.cli.commands import Version, Workspace
11+
from codegate.pipeline.cli.commands import SystemPrompt, Version, Workspace
1212

1313
HELP_TEXT = """
1414
## CodeGate CLI\n
@@ -32,6 +32,7 @@ async def codegate_cli(command):
3232
available_commands = {
3333
"version": Version().exec,
3434
"workspace": Workspace().exec,
35+
"system-prompt": SystemPrompt().exec,
3536
}
3637
out_func = available_commands.get(command[0])
3738
if out_func is None:

src/codegate/pipeline/cli/commands.py

+152-42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from abc import ABC, abstractmethod
2-
from typing import List
2+
from typing import Awaitable, Callable, Dict, List, Tuple
33

44
from pydantic import ValidationError
55

@@ -8,18 +8,29 @@
88
from codegate.workspaces.crud import WorkspaceCrud
99

1010

11+
class NoFlagValueError(Exception):
12+
pass
13+
14+
class NoSubcommandError(Exception):
15+
pass
16+
1117
class 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

Comments
 (0)