Merge branch 'main' of github.com:oraios/serena

Conflicts:
	src/serena/mcp.py
This commit is contained in:
Dominik Jain committed 2025-03-29 16:54:20 +01:00
commit 6b617fb047
6 files changed
+90 -88

No files matched your search

@@ -1,3 +1,7 @@
# ruff: noqa
# black: skip
# mypy: ignore-errors
from .multilang_prompt import MultiLangContainer, MultiLangPromptTemplateCollection, PromptList
-2
View File
@@ -18,8 +18,6 @@ classifiers = [
"Programming Language :: Python :: 3.11"
]
dependencies = [
"pandas>=2.2.1",
"plotly>=5.19.0",
"requests>=2.32.3,<3",
"pyright>=1.1.396,<2",
"overrides>=7.7.0,<8",
+4
View File
@@ -1,3 +1,7 @@
# ruff: noqa
# black: skip
# mypy: ignore-errors
from .multilang_prompt import MultiLangContainer, MultiLangPromptTemplateCollection, PromptList
+44 -3
View File
@@ -30,6 +30,7 @@ from serena.gui_log_viewer import GuiLogViewer, GuiLogViewerHandler
from serena.llm.prompt_factory import PromptFactory
from serena.symbol import SymbolLocation, SymbolManager
from serena.util.file_system import scan_directory
from serena.util.shell import execute_shell_command
log = logging.getLogger(__name__)
@@ -96,6 +97,7 @@ async def server_lifespan(mcp_server: FastMCP) -> AsyncIterator[SerenaMCPRequest
class MemoriesManager:
def __init__(self, memory_dir: str):
self._memory_dir = Path(memory_dir)
self._memory_dir.mkdir(parents=True, exist_ok=True)
def _get_memory_file_path(self, memory_file_name: str) -> Path:
return self._memory_dir / memory_file_name
@@ -589,7 +591,7 @@ def onboarding(ctx: Context) -> str:
@mcp.tool()
def write_memory(ctx: Context, memory_file_name: str, content: str) -> str:
def write_memory(ctx: Context, memory_file_name: str, content: str, max_answer_chars: int = _DEFAULT_MAX_ANSWER_LENGTH) -> str:
"""
Write some general information about this project that can be useful for future tasks to a memory file.
The information should be short and to the point.
@@ -600,6 +602,11 @@ def write_memory(ctx: Context, memory_file_name: str, content: str) -> str:
This tool is either called during the onboarding process or when you have identified
something worth remembering about the project from the past conversation.
"""
if len(content) > max_answer_chars:
raise ValueError(
f"Content for {memory_file_name } is too long. Max length is {max_answer_chars} characters. "
+ "Please make the content shorter."
)
class WriteMemoryTool(Tool):
def _execute(self) -> str:
@@ -609,7 +616,7 @@ def write_memory(ctx: Context, memory_file_name: str, content: str) -> str:
@mcp.tool()
def read_memory(ctx: Context, memory_file_name: str) -> str:
def read_memory(ctx: Context, memory_file_name: str, max_answer_chars: int = _DEFAULT_MAX_ANSWER_LENGTH) -> str:
"""
Read the content of a memory file. This tool should only be used if the information
is relevant to the current task. You should be able to infer whether the information
@@ -621,7 +628,7 @@ def read_memory(ctx: Context, memory_file_name: str) -> str:
def _execute(self) -> str:
return self.memories_manager.load_memory(memory_file_name)
return ReadMemoryTool(ctx).execute()
return ReadMemoryTool(ctx).execute(max_answer_chars=max_answer_chars)
@mcp.tool()
@@ -736,3 +743,37 @@ def search_files_for_pattern(
return json.dumps(file_to_matches)
return SearchInAllCodeTool(ctx).execute(max_answer_chars=max_answer_chars)
@mcp.tool()
def shell_command(
ctx: Context,
command: str,
cwd: str | None = None,
capture_stderr: bool = True,
max_answer_chars: int = _DEFAULT_MAX_ANSWER_LENGTH,
) -> str:
"""
Execute a shell command and return its output.
You should have at least once looked at the suggested shell commands from the corresponding memory
created during the onboarding process before using this tool.
Never execute unsafe shell commands like `rm -rf /` or similar! Generally be very careful with deletions.
:param ctx: the context object, which will be created and provided automatically
:param command: the shell command to execute
:param cwd: the working directory to execute the command in. If None, the project root will be used.
:param capture_stderr: whether to capture and return stderr output
:param max_answer_chars: if the output is longer than this number of characters,
no content will be returned. Don't adjust unless there is really no other way to get the content
required for the task.
:return: a JSON object containing the command's stdout and optionally stderr output
"""
log.info(f"execute_shell_command: {command=}")
class ExecuteShellCommandTool(Tool):
def _execute(self) -> str:
_cwd = cwd or self.project_root
result = execute_shell_command(command, cwd=_cwd, capture_stderr=capture_stderr)
return result.json()
return ExecuteShellCommandTool(ctx).execute(max_answer_chars=max_answer_chars)
+38
View File
@@ -0,0 +1,38 @@
import os
import subprocess
from pydantic import BaseModel
class ShellCommandResult(BaseModel):
stdout: str
return_code: int
cwd: str
stderr: str | None = None
def execute_shell_command(command: str, cwd: str | None = None, capture_stderr: bool = False) -> ShellCommandResult:
"""
Execute a shell command and return the output.
:param command: The command to execute.
:param cwd: The working directory to execute the command in. If None, the current working directory will be used.
:param capture_stderr: Whether to capture the stderr output.
:return: The output of the command.
"""
if cwd is None:
cwd = os.getcwd()
process = subprocess.Popen(
command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE if capture_stderr else None,
text=True,
encoding="utf-8",
errors="replace",
cwd=cwd,
)
stdout, stderr = process.communicate()
return ShellCommandResult(stdout=stdout, stderr=stderr, return_code=process.returncode, cwd=cwd)
Generated
-83
View File
@@ -1269,15 +1269,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/f6/6d61a023d758f488e36638076e8a4ec4447a2cdf86938cf6c60cf1c860e6/myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14", size = 77158 },
]
[[package]]
name = "narwhals"
version = "1.32.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c1/e5/aa97891440bf6bc4239e9b918d89fea58eb87dff1d8d14a69b45ef677e66/narwhals-1.32.0.tar.gz", hash = "sha256:bd0aa41434737adb4b26f8593f3559abc7d938730ece010fe727b58bc363580d", size = 258915 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/96/79a6168dc7a5098066e097c01a45d01608c8df6552dfb92a2676ce623186/narwhals-1.32.0-py3-none-any.whl", hash = "sha256:8bdbf3f76155887412eea04b0b06303856ac1aa3d9e8bda5b5e54612855fa560", size = 320073 },
]
[[package]]
name = "natsort"
version = "8.4.0"
@@ -1415,24 +1406,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307 },
]
[[package]]
name = "numpy"
version = "2.2.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/78/31103410a57bc2c2b93a3597340a8119588571f6a4539067546cb9a0bfac/numpy-2.2.4.tar.gz", hash = "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", size = 20270701 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/16/fb/09e778ee3a8ea0d4dc8329cca0a9c9e65fed847d08e37eba74cb7ed4b252/numpy-2.2.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e9e0a277bb2eb5d8a7407e14688b85fd8ad628ee4e0c7930415687b6564207a4", size = 21254989 },
{ url = "https://files.pythonhosted.org/packages/a2/0a/1212befdbecab5d80eca3cde47d304cad986ad4eec7d85a42e0b6d2cc2ef/numpy-2.2.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9eeea959168ea555e556b8188da5fa7831e21d91ce031e95ce23747b7609f8a4", size = 14425910 },
{ url = "https://files.pythonhosted.org/packages/2b/3e/e7247c1d4f15086bb106c8d43c925b0b2ea20270224f5186fa48d4fb5cbd/numpy-2.2.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bd3ad3b0a40e713fc68f99ecfd07124195333f1e689387c180813f0e94309d6f", size = 5426490 },
{ url = "https://files.pythonhosted.org/packages/5d/fa/aa7cd6be51419b894c5787a8a93c3302a1ed4f82d35beb0613ec15bdd0e2/numpy-2.2.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cf28633d64294969c019c6df4ff37f5698e8326db68cc2b66576a51fad634880", size = 6967754 },
{ url = "https://files.pythonhosted.org/packages/d5/ee/96457c943265de9fadeb3d2ffdbab003f7fba13d971084a9876affcda095/numpy-2.2.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fa8fa7697ad1646b5c93de1719965844e004fcad23c91228aca1cf0800044a1", size = 14373079 },
{ url = "https://files.pythonhosted.org/packages/c5/5c/ceefca458559f0ccc7a982319f37ed07b0d7b526964ae6cc61f8ad1b6119/numpy-2.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4162988a360a29af158aeb4a2f4f09ffed6a969c9776f8f3bdee9b06a8ab7e5", size = 16428819 },
{ url = "https://files.pythonhosted.org/packages/22/31/9b2ac8eee99e001eb6add9fa27514ef5e9faf176169057a12860af52704c/numpy-2.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:892c10d6a73e0f14935c31229e03325a7b3093fafd6ce0af704be7f894d95687", size = 15881470 },
{ url = "https://files.pythonhosted.org/packages/f0/dc/8569b5f25ff30484b555ad8a3f537e0225d091abec386c9420cf5f7a2976/numpy-2.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db1f1c22173ac1c58db249ae48aa7ead29f534b9a948bc56828337aa84a32ed6", size = 18218144 },
{ url = "https://files.pythonhosted.org/packages/5e/05/463c023a39bdeb9bb43a99e7dee2c664cb68d5bb87d14f92482b9f6011cc/numpy-2.2.4-cp311-cp311-win32.whl", hash = "sha256:ea2bb7e2ae9e37d96835b3576a4fa4b3a97592fbea8ef7c3587078b0068b8f09", size = 6606368 },
{ url = "https://files.pythonhosted.org/packages/8b/72/10c1d2d82101c468a28adc35de6c77b308f288cfd0b88e1070f15b98e00c/numpy-2.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:f7de08cbe5551911886d1ab60de58448c6df0f67d9feb7d1fb21e9875ef95e91", size = 12947526 },
]
[[package]]
name = "overrides"
version = "7.7.0"
@@ -1451,27 +1424,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
]
[[package]]
name = "pandas"
version = "2.2.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
{ name = "python-dateutil" },
{ name = "pytz" },
{ name = "tzdata" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222 },
{ url = "https://files.pythonhosted.org/packages/52/11/9eac327a38834f162b8250aab32a6781339c69afe7574368fffe46387edf/pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", size = 11321274 },
{ url = "https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", size = 15579836 },
{ url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505 },
{ url = "https://files.pythonhosted.org/packages/b9/57/708135b90391995361636634df1f1130d03ba456e95bcf576fada459115a/pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", size = 16744420 },
{ url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457 },
{ url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166 },
]
[[package]]
name = "pandocfilters"
version = "1.5.1"
@@ -1529,19 +1481,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499 },
]
[[package]]
name = "plotly"
version = "6.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "narwhals" },
{ name = "packaging" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c7/cc/e41b5f697ae403f0b50e47b7af2e36642a193085f553bf7cc1169362873a/plotly-6.0.1.tar.gz", hash = "sha256:dd8400229872b6e3c964b099be699f8d00c489a974f2cfccfad5e8240873366b", size = 8094643 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/65/ad2bc85f7377f5cfba5d4466d5474423a3fb7f6a97fd807c06f92dd3e721/plotly-6.0.1-py3-none-any.whl", hash = "sha256:4714db20fea57a435692c548a4eb4fae454f7daddf15f8d8ba7e1045681d7768", size = 14805757 },
]
[[package]]
name = "pluggy"
version = "1.5.0"
@@ -1841,15 +1780,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163 },
]
[[package]]
name = "pytz"
version = "2025.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5f/57/df1c9157c8d5a05117e455d66fd7cf6dbc46974f832b1058ed4856785d8a/pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e", size = 319617 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/eb/38/ac33370d784287baa1c3d538978b5e2ea064d4c1b93ffbd12826c190dd10/pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", size = 507930 },
]
[[package]]
name = "pywin32"
version = "310"
@@ -2080,8 +2010,6 @@ dependencies = [
{ name = "fastmcp" },
{ name = "mcp" },
{ name = "overrides" },
{ name = "pandas" },
{ name = "plotly" },
{ name = "pydantic" },
{ name = "pyright" },
{ name = "python-dotenv" },
@@ -2131,8 +2059,6 @@ requires-dist = [
{ name = "nbqa", marker = "extra == 'dev'", specifier = ">=1.7.1" },
{ name = "nbstripout", marker = "extra == 'dev'", specifier = ">=0.6.1" },
{ name = "overrides", specifier = ">=7.7.0,<8" },
{ name = "pandas", specifier = ">=2.2.1" },
{ name = "plotly", specifier = ">=5.19.0" },
{ name = "poethepoet", marker = "extra == 'dev'", specifier = ">=0.20.0" },
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.3.3" },
{ name = "pydantic", specifier = ">=2.10.6" },
@@ -2731,15 +2657,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
]
[[package]]
name = "tzdata"
version = "2025.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
]
[[package]]
name = "uc-micro-py"
version = "1.0.3"