mirror of
https://github.com/tiennm99/serena.git
synced 2026-09-03 08:19:19 +00:00
Buncha small fixes
This commit is contained in:
@@ -12,4 +12,4 @@ prompt: |
|
||||
excluded_tools:
|
||||
- get_current_config
|
||||
- activate_project
|
||||
- activate_modes
|
||||
- switch_modes
|
||||
|
||||
+32
-15
@@ -321,8 +321,8 @@ class SerenaAgent:
|
||||
context = SerenaAgentContext.load_default()
|
||||
if modes is None:
|
||||
modes = SerenaAgentMode.load_default_modes()
|
||||
self.context = context
|
||||
self.modes = modes
|
||||
self._context = context
|
||||
self._modes = modes
|
||||
self._update_active_tools()
|
||||
log.info(f"Loaded tools ({len(self._all_tools)}): {', '.join([tool.get_name() for tool in self._all_tools.values()])}")
|
||||
|
||||
@@ -368,15 +368,21 @@ class SerenaAgent:
|
||||
|
||||
:param modes: List of mode names or paths to use
|
||||
"""
|
||||
self.current_modes = modes
|
||||
self._modes = modes
|
||||
self._update_active_tools()
|
||||
|
||||
log.info(f"Set modes to {[mode.name for mode in modes]}")
|
||||
|
||||
def get_active_modes(self) -> list[SerenaAgentMode]:
|
||||
"""
|
||||
:return: the list of active modes
|
||||
"""
|
||||
return list(self._modes)
|
||||
|
||||
def create_system_prompt(self) -> str:
|
||||
return self.prompt_factory.create_system_prompt(
|
||||
context_system_prompt=self.context.prompt,
|
||||
mode_system_prompts=[mode.prompt for mode in self.current_modes],
|
||||
context_system_prompt=self._context.prompt,
|
||||
mode_system_prompts=[mode.prompt for mode in self._modes],
|
||||
)
|
||||
|
||||
def _update_active_tools(self) -> None:
|
||||
@@ -390,9 +396,9 @@ class SerenaAgent:
|
||||
"""
|
||||
# Collect all excluded tools with the desired priority mode < context < project
|
||||
excluded_tool_classes: set[type[Tool]] = set()
|
||||
for mode in self.current_modes:
|
||||
for mode in self._modes:
|
||||
excluded_tool_classes.update(mode.get_excluded_tool_classes())
|
||||
excluded_tool_classes.update(self.context.get_excluded_tool_classes())
|
||||
excluded_tool_classes.update(self._context.get_excluded_tool_classes())
|
||||
if self.project_config is not None:
|
||||
excluded_tool_classes.update(self.project_config.get_excluded_tool_classes())
|
||||
|
||||
@@ -440,6 +446,24 @@ class SerenaAgent:
|
||||
"""
|
||||
return sorted([tool.get_name() for tool in self._active_tools.values()])
|
||||
|
||||
def get_current_config_overview(self) -> str:
|
||||
"""
|
||||
:return: a string overview of the current configuration, including the active project, context, modes, and tools
|
||||
"""
|
||||
result_str = "Current configuration:\n"
|
||||
if self.project_config is not None:
|
||||
result_str += f"Active project: {self.project_config.project_name}\n"
|
||||
result_str += f"Active context: {self._context.name}\n"
|
||||
result_str += "Active modes: {}\n".format(", ".join([mode.name for mode in self.get_active_modes()]))
|
||||
result_str += "Active tools (after all exclusions from the project, context, and modes):\n"
|
||||
active_tool_names = self.get_active_tool_names()
|
||||
# print the tool names in chunks
|
||||
chunk_size = 4
|
||||
for i in range(0, len(active_tool_names), chunk_size):
|
||||
chunk = active_tool_names[i : i + chunk_size]
|
||||
result_str += " " + ", ".join(chunk) + "\n"
|
||||
return result_str
|
||||
|
||||
def is_language_server_running(self) -> bool:
|
||||
return self.language_server is not None and self.language_server.is_running()
|
||||
|
||||
@@ -1528,14 +1552,7 @@ class GetCurrentConfigTool(Tool):
|
||||
"""
|
||||
Print the current configuration of the agent, including the active modes, tools, and context.
|
||||
"""
|
||||
result_str = "Current configuration:\n"
|
||||
if self.agent.project_config is not None:
|
||||
result_str += f"Active project: {self.agent.project_config.project_name}\n"
|
||||
result_str += f"Active context: {self.agent.context.name}\n"
|
||||
result_str += "Active modes: {}\n".format(", ".join([mode.name for mode in self.agent.current_modes]))
|
||||
result_str += "Active tools (exclusions from the project, context, and modes):\n"
|
||||
result_str += "\n".join(self.agent.get_active_tool_names())
|
||||
return result_str
|
||||
return self.agent.get_current_config_overview()
|
||||
|
||||
|
||||
class InitialInstructionsTool(Tool):
|
||||
|
||||
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Self
|
||||
import yaml
|
||||
from sensai.util import logging
|
||||
|
||||
from serena.constants import CONTEXT_YAMLS_DIR, MODE_YAMLS_DIR
|
||||
from serena.constants import CONTEXT_YAMLS_DIR, DEFAULT_CONTEXT, DEFAULT_MODES, MODE_YAMLS_DIR
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from serena.agent import Tool
|
||||
@@ -69,7 +69,7 @@ class SerenaAgentMode:
|
||||
@classmethod
|
||||
def load_default_modes(cls) -> list[Self]:
|
||||
"""Load the default modes (interactive and editing)."""
|
||||
return [cls.from_name("interactive"), cls.from_name("editing")]
|
||||
return [cls.from_name(mode) for mode in DEFAULT_MODES]
|
||||
|
||||
@classmethod
|
||||
def load(cls, name_or_path: str | Path) -> Self:
|
||||
@@ -111,8 +111,8 @@ class SerenaAgentContext:
|
||||
yaml_path = os.path.join(CONTEXT_YAMLS_DIR, f"{name}.yml")
|
||||
if not os.path.exists(yaml_path):
|
||||
raise FileNotFoundError(
|
||||
f"Context {Path(yaml_path).stem} not found in {CONTEXT_YAMLS_DIR}. You can load a custom context by using from_yaml() instead. "
|
||||
f"Available contexts: {cls.list_registered_context_names()}"
|
||||
f"Context {Path(yaml_path).stem} not found in {CONTEXT_YAMLS_DIR}. You can load a custom context by using from_yaml() instead.\n"
|
||||
f"Available contexts:\n{cls.list_registered_context_names()}"
|
||||
)
|
||||
return cls.from_yaml(yaml_path)
|
||||
|
||||
@@ -131,7 +131,7 @@ class SerenaAgentContext:
|
||||
@classmethod
|
||||
def load_default(cls) -> Self:
|
||||
"""Load the default context."""
|
||||
return cls.from_name("default")
|
||||
return cls.from_name(DEFAULT_CONTEXT)
|
||||
|
||||
def print_overview(self) -> None:
|
||||
"""Print an overview of the mode."""
|
||||
|
||||
@@ -6,3 +6,6 @@ REPO_ROOT = str(_repo_root_path)
|
||||
PROMPT_TEMPLATES_DIR = str(_repo_root_path / "config" / "prompt_templates")
|
||||
CONTEXT_YAMLS_DIR = str(_repo_root_path / "config" / "contexts")
|
||||
MODE_YAMLS_DIR = str(_repo_root_path / "config" / "modes")
|
||||
|
||||
DEFAULT_CONTEXT = "desktop-app"
|
||||
DEFAULT_MODES = ("interactive", "editing")
|
||||
|
||||
+19
-16
@@ -20,6 +20,7 @@ from sensai.util.helper import mark_used
|
||||
|
||||
from serena.agent import SerenaAgent, Tool, show_fatal_exception_safe
|
||||
from serena.config import SerenaAgentContext, SerenaAgentMode
|
||||
from serena.constants import DEFAULT_CONTEXT, DEFAULT_MODES
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
LOG_FORMAT = "%(levelname)-5s %(asctime)-15s %(name)s:%(funcName)s:%(lineno)d - %(message)s"
|
||||
@@ -94,9 +95,13 @@ def make_tool(
|
||||
)
|
||||
|
||||
|
||||
def create_mcp_server(
|
||||
project_file_path: str | None, host: str = "0.0.0.0", port: int = 8000, context: str = "default", modes: Sequence[str] = ("default",)
|
||||
) -> FastMCP:
|
||||
def create_mcp_server_and_agent(
|
||||
project_file_path: str | None,
|
||||
host: str = "0.0.0.0",
|
||||
port: int = 8000,
|
||||
context: str = DEFAULT_CONTEXT,
|
||||
modes: Sequence[str] = DEFAULT_MODES,
|
||||
) -> tuple[FastMCP, SerenaAgent]:
|
||||
"""
|
||||
Create an MCP server.
|
||||
|
||||
@@ -147,7 +152,7 @@ def create_mcp_server(
|
||||
|
||||
update_tools()
|
||||
|
||||
return mcp
|
||||
return mcp, agent
|
||||
|
||||
|
||||
@click.command()
|
||||
@@ -169,7 +174,8 @@ def create_mcp_server(
|
||||
@click.option(
|
||||
"--context",
|
||||
type=str,
|
||||
default="desktop-app",
|
||||
show_default=True,
|
||||
default=DEFAULT_CONTEXT,
|
||||
help="Context to use. This can be a name of a built-in context ('desktop-app', 'agent', 'ide-assistant') "
|
||||
"or a path to a custom context YAML file.",
|
||||
)
|
||||
@@ -178,7 +184,8 @@ def create_mcp_server(
|
||||
"modes",
|
||||
type=str,
|
||||
multiple=True,
|
||||
default=["editing", "interactive"],
|
||||
default=DEFAULT_MODES,
|
||||
show_default=True,
|
||||
help="Mode(s) to use. This can be names of built-in modes ('planning', 'editing', 'one-shot', 'interactive') "
|
||||
"or paths to custom mode YAML files. Can be specified multiple times to combine modes.",
|
||||
)
|
||||
@@ -192,22 +199,22 @@ def create_mcp_server(
|
||||
@click.option(
|
||||
"--host",
|
||||
type=str,
|
||||
default="0.0.0.0",
|
||||
show_default=True,
|
||||
default="0.0.0.0",
|
||||
help="Host to bind to (for SSE transport).",
|
||||
)
|
||||
@click.option(
|
||||
"--port",
|
||||
type=int,
|
||||
default=8000,
|
||||
show_default=True,
|
||||
default=8000,
|
||||
help="Port to bind to (for SSE transport).",
|
||||
)
|
||||
def start_mcp_server(
|
||||
project_file_opt: str | None,
|
||||
project_file_arg: str | None,
|
||||
context: str,
|
||||
modes: tuple[str, ...],
|
||||
context: str = DEFAULT_CONTEXT,
|
||||
modes: tuple[str, ...] = DEFAULT_MODES,
|
||||
transport: Literal["stdio", "sse"] = "stdio",
|
||||
host: str = "0.0.0.0",
|
||||
port: int = 8000,
|
||||
@@ -222,7 +229,7 @@ def start_mcp_server(
|
||||
# This is for backward compatibility with the old CLI, should be removed in the future!
|
||||
project_file = project_file_arg if project_file_arg is not None else project_file_opt
|
||||
|
||||
mcp_server = create_mcp_server(project_file_path=project_file, host=host, port=port, context=context, modes=modes)
|
||||
mcp_server, agent = create_mcp_server_and_agent(project_file_path=project_file, host=host, port=port, context=context, modes=modes)
|
||||
|
||||
# log after server creation such that the log appears in the GUI
|
||||
if project_file_arg is not None:
|
||||
@@ -232,10 +239,6 @@ def start_mcp_server(
|
||||
f"Used path: {project_file}"
|
||||
)
|
||||
|
||||
# Log selected context and modes
|
||||
if context:
|
||||
log.info(f"Using context: {context}")
|
||||
if modes:
|
||||
log.info(f"Using modes: {', '.join(modes)}")
|
||||
log.info(f"Starting serena agent in MCP server with config:\n{agent.get_current_config_overview()}")
|
||||
|
||||
mcp_server.run(transport=transport)
|
||||
|
||||
Reference in New Issue
Block a user