mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 06:15:43 +00:00
Support --mode and --context with yaml files
This commit is contained in:
1 parent
72ce32a65a
commit
870aa2cc3a
2 files changed
+58
-14
No files matched your search
@@ -41,6 +41,11 @@ class SerenaAgentMode(ToolInclusionDefinition, ToStringMixin):
|
||||
It is formatted by the agent (see SerenaAgent._format_prompt()).
|
||||
"""
|
||||
description: str = ""
|
||||
_yaml_path: Path | None = field(default=None, repr=False, compare=False)
|
||||
"""
|
||||
Internal field storing the path to the YAML file this mode was loaded from.
|
||||
Used to support loading modes from arbitrary file paths.
|
||||
"""
|
||||
|
||||
def _tostring_includes(self) -> list[str]:
|
||||
return ["name"]
|
||||
@@ -54,14 +59,24 @@ class SerenaAgentMode(ToolInclusionDefinition, ToStringMixin):
|
||||
@classmethod
|
||||
def from_yaml(cls, yaml_path: str | Path) -> Self:
|
||||
"""Load a mode from a YAML file."""
|
||||
with open(yaml_path, encoding=SERENA_FILE_ENCODING) as f:
|
||||
yaml_as_path = Path(yaml_path).resolve()
|
||||
with Path(yaml_as_path).open(encoding=SERENA_FILE_ENCODING) as f:
|
||||
data = yaml.safe_load(f)
|
||||
name = data.pop("name", Path(yaml_path).stem)
|
||||
return cls(name=name, **data)
|
||||
name = data.pop("name", yaml_as_path.stem)
|
||||
return cls(name=name, _yaml_path=yaml_as_path, **data)
|
||||
|
||||
@classmethod
|
||||
def get_path(cls, name: str) -> str:
|
||||
"""Get the path to the YAML file for a mode."""
|
||||
def get_path(cls, name: str, instance: Self | None = None) -> str:
|
||||
"""Get the path to the YAML file for a mode.
|
||||
|
||||
:param name: The name of the mode
|
||||
:param instance: Optional mode instance. If provided and it has a stored path, that path is returned.
|
||||
:return: The path to the mode's YAML file
|
||||
"""
|
||||
# If we have an instance with a stored path, use that
|
||||
if instance is not None and instance._yaml_path is not None:
|
||||
return str(instance._yaml_path)
|
||||
|
||||
fname = f"{name}.yml"
|
||||
custom_mode_path = os.path.join(SerenaPaths().user_modes_dir, fname)
|
||||
if os.path.exists(custom_mode_path):
|
||||
@@ -137,6 +152,12 @@ class SerenaAgentContext(ToolInclusionDefinition, ToStringMixin):
|
||||
maps tool names to custom descriptions, default descriptions are extracted from the tool docstrings.
|
||||
"""
|
||||
|
||||
_yaml_path: Path | None = field(default=None, repr=False, compare=False)
|
||||
"""
|
||||
Internal field storing the path to the YAML file this context was loaded from.
|
||||
Used to support loading contexts from arbitrary file paths.
|
||||
"""
|
||||
|
||||
single_project: bool = False
|
||||
"""
|
||||
whether to assume that Serena shall only work on a single project in this context (provided that a project is given
|
||||
@@ -152,17 +173,27 @@ class SerenaAgentContext(ToolInclusionDefinition, ToStringMixin):
|
||||
@classmethod
|
||||
def from_yaml(cls, yaml_path: str | Path) -> Self:
|
||||
"""Load a context from a YAML file."""
|
||||
with open(yaml_path, encoding=SERENA_FILE_ENCODING) as f:
|
||||
yaml_as_path = Path(yaml_path).resolve()
|
||||
with yaml_as_path.open(encoding=SERENA_FILE_ENCODING) as f:
|
||||
data = yaml.safe_load(f)
|
||||
name = data.pop("name", Path(yaml_path).stem)
|
||||
name = data.pop("name", yaml_as_path.stem)
|
||||
# Ensure backwards compatibility for tool_description_overrides
|
||||
if "tool_description_overrides" not in data:
|
||||
data["tool_description_overrides"] = {}
|
||||
return cls(name=name, **data)
|
||||
return cls(name=name, _yaml_path=yaml_as_path, **data)
|
||||
|
||||
@classmethod
|
||||
def get_path(cls, name: str) -> str:
|
||||
"""Get the path to the YAML file for a context."""
|
||||
def get_path(cls, name: str, instance: Self | None = None) -> str:
|
||||
"""Get the path to the YAML file for a context.
|
||||
|
||||
:param name: The name of the context
|
||||
:param instance: Optional context instance. If provided and it has a stored path, that path is returned.
|
||||
:return: The path to the context's YAML file
|
||||
"""
|
||||
# If we have an instance with a stored path, use that
|
||||
if instance is not None and instance._yaml_path is not None:
|
||||
return str(instance._yaml_path)
|
||||
|
||||
fname = f"{name}.yml"
|
||||
custom_context_path = os.path.join(SerenaPaths().user_contexts_dir, fname)
|
||||
if os.path.exists(custom_context_path):
|
||||
|
||||
+17
-4
@@ -354,12 +354,15 @@ class SerenaDashboardAPI:
|
||||
context_info = {
|
||||
"name": context.name,
|
||||
"description": context.description,
|
||||
"path": SerenaAgentContext.get_path(context.name),
|
||||
"path": SerenaAgentContext.get_path(context.name, instance=context),
|
||||
}
|
||||
|
||||
# Get active modes
|
||||
modes = self._agent.get_active_modes()
|
||||
modes_info = [{"name": mode.name, "description": mode.description, "path": SerenaAgentMode.get_path(mode.name)} for mode in modes]
|
||||
modes_info = [
|
||||
{"name": mode.name, "description": mode.description, "path": SerenaAgentMode.get_path(mode.name, instance=mode)}
|
||||
for mode in modes
|
||||
]
|
||||
active_mode_names = [mode.name for mode in modes]
|
||||
|
||||
# Get active tools
|
||||
@@ -392,11 +395,16 @@ class SerenaDashboardAPI:
|
||||
all_mode_names = SerenaAgentMode.list_registered_mode_names()
|
||||
available_modes: list[dict[str, str | bool]] = []
|
||||
for mode_name in all_mode_names:
|
||||
try:
|
||||
mode_path = SerenaAgentMode.get_path(mode_name)
|
||||
except FileNotFoundError:
|
||||
# Skip modes that can't be found (shouldn't happen for registered modes)
|
||||
continue
|
||||
available_modes.append(
|
||||
{
|
||||
"name": mode_name,
|
||||
"is_active": mode_name in active_mode_names,
|
||||
"path": SerenaAgentMode.get_path(mode_name),
|
||||
"path": mode_path,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -404,11 +412,16 @@ class SerenaDashboardAPI:
|
||||
all_context_names = SerenaAgentContext.list_registered_context_names()
|
||||
available_contexts: list[dict[str, str | bool]] = []
|
||||
for context_name in all_context_names:
|
||||
try:
|
||||
context_path = SerenaAgentContext.get_path(context_name)
|
||||
except FileNotFoundError:
|
||||
# Skip contexts that can't be found (shouldn't happen for registered contexts)
|
||||
continue
|
||||
available_contexts.append(
|
||||
{
|
||||
"name": context_name,
|
||||
"is_active": context_name == context.name,
|
||||
"path": SerenaAgentContext.get_path(context_name),
|
||||
"path": context_path,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in new issue
Block a user