Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

fix: solve problems with codegate cli and previous context #757

Merged
merged 6 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions src/codegate/pipeline/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
PipelineStep,
)
from codegate.pipeline.cli.commands import CustomInstructions, Version, Workspace
from codegate.utils.utils import get_tool_name_from_messages

HELP_TEXT = """
## CodeGate CLI\n
Expand Down Expand Up @@ -77,27 +78,52 @@ async def process(

if last_user_message is not None:
last_user_message_str, _ = last_user_message
cleaned_message_str = re.sub(r"<.*?>", "", last_user_message_str).strip()
splitted_message = cleaned_message_str.lower().split(" ")
# We expect codegate as the first word in the message
if splitted_message[0] == "codegate":
context.shortcut_response = True
args = shlex.split(cleaned_message_str)
cmd_out = await codegate_cli(args[1:])

if cleaned_message_str != last_user_message_str:
# it came from Cline, need to wrap into tags
cmd_out = (
f"<attempt_completion><result>{cmd_out}</result></attempt_completion>\n"
)
return PipelineResult(
response=PipelineResponse(
step_name=self.name,
content=cmd_out,
model=request["model"],
),
context=context,
last_user_message_str = last_user_message_str.strip()
base_tool = get_tool_name_from_messages(request)
codegate_regex = re.compile(r"^codegate(?:\s+(.*))?", re.IGNORECASE)

if base_tool and base_tool == "cline":
# Check if there are <task> or <feedback> tags
tag_match = re.search(
r"<(task|feedback)>(.*?)</\1>", last_user_message_str, re.DOTALL
)
if tag_match:
# Extract the content between the tags
stripped_message = tag_match.group(2).strip()
else:
# If no <task> or <feedback> tags, use the entire message
stripped_message = last_user_message_str.strip()

# Remove all other XML tags and trim whitespace
stripped_message = re.sub(r"<[^>]+>", "", stripped_message).strip()

# Check if "codegate" is the first word
match = codegate_regex.match(stripped_message)
else:
# Check if "codegate" is the first word in the message
match = codegate_regex.match(last_user_message_str)
if match:
command = match.group(1) or ""
command = command.strip()

# Process the command
args = shlex.split(f"codegate {command}")
if args:
context.shortcut_response = True
cmd_out = await codegate_cli(args[1:])
if base_tool and base_tool == "cline":
cmd_out = (
f"<attempt_completion><result>{cmd_out}</result></attempt_completion>\n"
)

return PipelineResult(
response=PipelineResponse(
step_name=self.name,
content=cmd_out,
model=request["model"],
),
context=context,
)

# Fall through
return PipelineResult(request=request, context=context)
5 changes: 4 additions & 1 deletion src/codegate/providers/copilot/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,15 @@ async def _forward_data_through_pipeline(self, data: bytes) -> Union[HttpRequest
# we couldn't parse this into an HTTP request, so we just pass through
return data

body, context = await self._body_through_pipeline(
result = await self._body_through_pipeline(
http_request.method,
http_request.path,
http_request.headers,
http_request.body,
)
if not result:
return data
body, context = result
# TODO: it's weird that we're overwriting the context.
# Should we set the context once? Maybe when
# creating the pipeline instance?
Expand Down
22 changes: 22 additions & 0 deletions src/codegate/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,25 @@ def generate_vector_string(package) -> str:
# add description
vector_str += f" - Package offers this functionality: {package['description']}"
return vector_str


def get_tool_name_from_messages(data):
"""
Identifies the tool name based on the content of the messages.

Args:
request (dict): The request object containing messages.
tools (list): A list of tool names to search for.

Returns:
str: The name of the tool found in the messages, or None if no match is found.
"""
tools = [
"Cline",
]
for message in data.get("messages", []):
message_content = str(message.get("content", ""))
for tool in tools:
if tool in message_content:
return tool.lower()
return None
Loading