mirror of
https://github.com/tiennm99/serena.git
synced 2026-09-03 20:22:54 +00:00
Merge branch 'main' into fix-stability-issues
Conflicts: src/serena/agent.py
This commit is contained in:
@@ -69,21 +69,25 @@ Coming soon: Kotlin and Dart.
|
||||
|
||||
<!-- Created with markdown-toc -i README.md -->
|
||||
<!-- Install it with npm install -g markdown-toc -->
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Is It Really Free to Use?](#is-it-really-free-to-use)
|
||||
- [What Can I Use Serena For?](#what-can-i-use-serena-for)
|
||||
- [Quick Start](#quick-start)
|
||||
* [MCP Server (Claude Desktop)](#mcp-server-claude-desktop)
|
||||
* [Agno](#agno)
|
||||
* [Other MCP Clients - Cline, Roo-Code, Cursor, Windsurf etc.](#other-mcp-clients---cline-roo-code-cursor-windsurf-etc)
|
||||
* [Agno Agent](#agno-agent)
|
||||
* [Other Agent Frameworks](#other-agent-frameworks)
|
||||
- [Serena's Tools and Configuration](#serenas-tools-and-configuration)
|
||||
- [Comparison with Other Coding Agents](#comparison-with-other-coding-agents)
|
||||
* [Subscription-Based Coding Agents](#subscription-based-coding-agents)
|
||||
* [API-Based Coding Agents](#api-based-coding-agents)
|
||||
* [Other MCP-Based Coding Agents](#other-mcp-based-coding-agents)
|
||||
- [Limitations of MCP Servers](#limitations-of-mcp-servers)
|
||||
- [Stability Issues in MCP Client-Server Interactions](#stability-issues-in-mcp-client-server-interactions)
|
||||
* [Serena Logging](#serena-logging)
|
||||
- [Onboarding and Memories](#onboarding-and-memories)
|
||||
- [Combination with Other MCP Servers](#combination-with-other-mcp-servers)
|
||||
- [Recommendations on Using Serena](#recommendations-on-using-serena)
|
||||
* [Which Model to Choose?](#which-model-to-choose)
|
||||
* [Onboarding](#onboarding)
|
||||
@@ -147,12 +151,22 @@ Serena can read, write and execute code, read logs and the terminal output.
|
||||
If you are using paths containing backslashes for paths on Windows
|
||||
(note that you can also just use forward slashes), be sure to escape them correctly (`\\`).
|
||||
|
||||
That's it! Save the config and then restart Claude Desktop.
|
||||
That's it! Save the config and then restart Claude Desktop.
|
||||
|
||||
Note: on Windows and MacOS there are official Claude Desktop applications by Anthropic, for Linux there is an [open-source
|
||||
community version](https://github.com/aaddrick/claude-desktop-debian).
|
||||
|
||||
⚠️ Be sure to fully quit the Claude Desktop application, as closing Claude will just minimize it to the system tray – at least on Windows.
|
||||
|
||||
After restarting, you should see Serena's tools in your chat interface (notice the small hammer icon).
|
||||
|
||||
⚠️ Tool Names: Claude Desktop (and most MCP Clients) don't resolve the name of the server. So you shouldn't
|
||||
say something like "use Serena's tools". Instead, you can instruct the LLM to use symbolic tools or to
|
||||
use a particular tool by referring to its name. Moreover, if you use multiple MCP Servers, you might get
|
||||
**tool name collisions** which lead to undefined behavior. For example, Serena is currently incompatible with the
|
||||
[Filesystem MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) due to tool name
|
||||
collisions.
|
||||
|
||||
ℹ️ Note that MCP servers which use stdio as a protocol are somewhat unusual as far as client/server architectures go, as the server
|
||||
necessarily has to be started by the client in order for communication to take place via the server's standard input/output stream.
|
||||
In other words, you do not need to start the server yourself. The client application (e.g. Claude Desktop) takes care of this and
|
||||
@@ -163,12 +177,34 @@ write a new configuration file, adjust the configuration to point to it and then
|
||||
|
||||
For more information on MCP servers with Claude Desktop, see [the official quick start guide](https://modelcontextprotocol.io/quickstart/user).
|
||||
|
||||
### Agno
|
||||
### Other MCP Clients - Cline, Roo-Code, Cursor, Windsurf etc.
|
||||
|
||||
Agno is a model-agnostic agent framework that allows you to use Serena with a large number of underlying LLMs.
|
||||
Being an MCP Server, Serena can be included in any MCP Client. The same config as above,
|
||||
maybe with small client-specific modifications should work. Most of the popular
|
||||
existing coding assistants (IDE extensions or VSCode-like IDEs) accept connecting
|
||||
to MCP Servers. Including Serena generally boosts their performance
|
||||
by providing them tools for symbolic operations.
|
||||
|
||||
In this case, the billing for the usage continues to be controlled by the client of your choice
|
||||
(unlike with the Claude Desktop client). But you may still want to use Serena through such an approach,
|
||||
e.g., for one of the following reasons:
|
||||
|
||||
1. You are already using a coding assistant (say Cline or Cursor) and just want to make it more powerful.
|
||||
2. You are on Linux and don't want to use the [community-created Claude Desktop](https://github.com/aaddrick/claude-desktop-debian)
|
||||
3. You want tighter integration of Serena into your IDE and don't mind paying for that
|
||||
|
||||
The same considerations as in using Serena for Claude Desktop (in particular, tool name collisions)
|
||||
also apply here.
|
||||
|
||||
### Agno Agent
|
||||
|
||||
Agno is a model-agnostic agent framework that allows you to turn Serena into an agent
|
||||
(independent of the MCP technology) with a large number of underlying LLMs.
|
||||
|
||||
While Agno is not yet entirely stable, we chose it, because it comes with its own open-source UI,
|
||||
making it easy to directly use the agent using a chat interface.
|
||||
making it easy to directly use the agent using a chat interface. With Agno, Serena is turned into an agent
|
||||
(so no longer an MCP Server), so it can be used in programmatic ways (for example for benchmarking or within
|
||||
your application).
|
||||
|
||||
Here's how it works (see also [Agno's documentation](https://docs.agno.com/introduction/playground)):
|
||||
|
||||
@@ -221,6 +257,14 @@ this in our testing with Claude, allowing this may not be entirely safe.
|
||||
You may choose to disable certain tools for your setup in your Serena project's
|
||||
configuration file (`.yml`).
|
||||
|
||||
### Other Agent Frameworks
|
||||
|
||||
The Agno agent is particularly nice because of the Agno UI, but it is easy to incorporate Serena into any
|
||||
agent framework (like [pydantic-ai](https://ai.pydantic.dev/), [langgraph](https://langchain-ai.github.io/langgraph/tutorials/introduction/) or others).
|
||||
|
||||
You just have to write an adapter of Serena's tools to the tools in the framework of your choice, like
|
||||
it was done by us for agno in the [SerenaAgnoToolkit](/src/serena/agno.py).
|
||||
|
||||
## Serena's Tools and Configuration
|
||||
|
||||
Serena combines tools for semantic code retrieval with editing capabilities and shell execution.
|
||||
@@ -351,6 +395,14 @@ Every file in the `.serena/memories/` directory is a memory file.
|
||||
We found the memories to significantly improve the user experience with Serena.
|
||||
By itself, Serena is instructed to create new memories whenever appropriate.
|
||||
|
||||
## Combination with Other MCP Servers
|
||||
|
||||
When using Serena through an MCP Client, you can use it together with other MCP servers.
|
||||
However, beware of tool name collisions! See info on that above.
|
||||
|
||||
Currently, there is a collision with the popular Filesystem MCP Server. Since Serena also provides
|
||||
filesystem operations, there is likely no need to ever enable these two simultaneously.
|
||||
|
||||
## Recommendations on Using Serena
|
||||
|
||||
We will continue to collect best practices as the Serena community grows. Below a
|
||||
@@ -489,7 +541,8 @@ Without these projects, Serena would not have been possible (or would have been
|
||||
|
||||
It is very easy to extend Serena's AI functionality with your own ideas.
|
||||
Just implement a new Tool by subclassing from
|
||||
`serena.agent.Tool`. By default, the `SerenaAgent` will immediately have access to it.
|
||||
`serena.agent.Tool` and implement the `apply` method (not part of the interface, see
|
||||
comment in `Tool`). By default, the `SerenaAgent` will immediately have access to it.
|
||||
|
||||
It is also relatively straightforward to add [support for a new language](/CONTRIBUTING.md#adding-a-new-supported-language). We look forward to seeing what the community will come up with!
|
||||
For details on contributing, see [here](/CONTRIBUTING.md).
|
||||
|
||||
+12
-5
@@ -222,6 +222,16 @@ _DEFAULT_MAX_ANSWER_LENGTH = int(2e5)
|
||||
|
||||
|
||||
class Tool(Component):
|
||||
# NOTE: each tool should implement the apply method, which is then used in
|
||||
# the central method of the Tool class `apply_ex`.
|
||||
# Failure to do so will result in a RuntimeError at tool execution time.
|
||||
# The apply method is not declared as part of the base Tool interface since we cannot
|
||||
# know the signature of the (input parameters of the) method in advance.
|
||||
#
|
||||
# The docstring and types of the apply method are used to generate the tool description
|
||||
# (which is use by the LLM, so a good description is important)
|
||||
# and to validate the tool call arguments.
|
||||
|
||||
@classmethod
|
||||
def get_name(cls) -> str:
|
||||
name = cls.__name__
|
||||
@@ -234,7 +244,7 @@ class Tool(Component):
|
||||
def get_apply_fn(self) -> Callable:
|
||||
apply_fn = getattr(self, "apply")
|
||||
if apply_fn is None:
|
||||
raise Exception(f"{self} does not define method apply")
|
||||
raise RuntimeError(f"apply not defined in {self}. Did you forget to implement it?")
|
||||
return apply_fn
|
||||
|
||||
@classmethod
|
||||
@@ -279,10 +289,7 @@ class Tool(Component):
|
||||
if not self.language_server.is_running():
|
||||
self.agent.reset_language_server()
|
||||
|
||||
apply_fn = getattr(self, "apply")
|
||||
if apply_fn is None:
|
||||
raise ValueError(f"apply not defined in {self}")
|
||||
|
||||
apply_fn = self.get_apply_fn()
|
||||
if log_call:
|
||||
self._log_tool_application(inspect.currentframe())
|
||||
try:
|
||||
|
||||
@@ -321,6 +321,23 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/87/9ce47ede79878962f2f162e1d56e40bfbc9cf7a364963d72930589c3c62e/google_genai-1.8.0-py3-none-any.whl", hash = "sha256:b44bd67aa158313ab679d499e4e1666ca7b6363beb24f0d2149983c09460811a", size = 145696 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "greenlet"
|
||||
version = "3.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/28/62/1c2665558618553c42922ed47a4e6d6527e2fa3516a8256c2f431c5d0441/greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", size = 272479 },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/9d/421e2d5f07285b6e4e3a676b016ca781f63cfe4a0cd8eaecf3fd6f7a71ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", size = 640404 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/de/6e05f5c59262a584e502dd3d261bbdd2c97ab5416cc9c0b91ea38932a901/greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", size = 652813 },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/93/d5f93c84241acdea15a8fd329362c2c71c79e1a507c3f142a5d67ea435ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", size = 648517 },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/85/72f77fc02d00470c86a5c982b8daafdf65d38aefbbe441cebff3bf7037fc/greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", size = 647831 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", size = 602413 },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/70/ad6e5b31ef330f03b12559d19fda2606a522d3849cde46b24f223d6d1619/greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", size = 1129619 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/fb/201e1b932e584066e0f0658b538e73c459b34d44b4bd4034f682423bc801/greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", size = 1155198 },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/da/b9ed5e310bb8b89661b80cbcd4db5a067903bbcd7fc854923f5ebb4144f0/greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", size = 298930 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
@@ -946,6 +963,7 @@ dependencies = [
|
||||
agno = [
|
||||
{ name = "agno" },
|
||||
{ name = "fastapi" },
|
||||
{ name = "sqlalchemy" },
|
||||
]
|
||||
anthropic = [
|
||||
{ name = "anthropic" },
|
||||
@@ -989,6 +1007,7 @@ requires-dist = [
|
||||
{ name = "requests", specifier = ">=2.32.3,<3" },
|
||||
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.0.285" },
|
||||
{ name = "sensai-utils", specifier = ">=1.4.0" },
|
||||
{ name = "sqlalchemy", marker = "extra == 'agno'", specifier = ">=2.0.40" },
|
||||
{ name = "toml-sort", marker = "extra == 'dev'", specifier = ">=0.24.2" },
|
||||
{ name = "types-pyyaml", specifier = ">=6.0.12.20241230" },
|
||||
{ name = "types-pyyaml", marker = "extra == 'dev'", specifier = ">=6.0.12.20241230" },
|
||||
@@ -1022,6 +1041,27 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.40"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/c3/3f2bfa5e4dcd9938405fe2fab5b6ab94a9248a4f9536ea2fd497da20525f/sqlalchemy-2.0.40.tar.gz", hash = "sha256:d827099289c64589418ebbcaead0145cd19f4e3e8a93919a0100247af245fa00", size = 9664299 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/77/7e/55044a9ec48c3249bb38d5faae93f09579c35e862bb318ebd1ed7a1994a5/sqlalchemy-2.0.40-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f6bacab7514de6146a1976bc56e1545bee247242fab030b89e5f70336fc0003e", size = 2114025 },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/0f/dcf7bba95f847aec72f638750747b12d37914f71c8cc7c133cf326ab945c/sqlalchemy-2.0.40-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5654d1ac34e922b6c5711631f2da497d3a7bffd6f9f87ac23b35feea56098011", size = 2104419 },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/70/c86a5c20715e4fe903dde4c2fd44fc7e7a0d5fb52c1b954d98526f65a3ea/sqlalchemy-2.0.40-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35904d63412db21088739510216e9349e335f142ce4a04b69e2528020ee19ed4", size = 3222720 },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/cf/b891a8c1d0c27ce9163361664c2128c7a57de3f35000ea5202eb3a2917b7/sqlalchemy-2.0.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7a80ed86d6aaacb8160a1caef6680d4ddd03c944d985aecee940d168c411d1", size = 3222682 },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/3f/7709d8c8266953d945435a96b7f425ae4172a336963756b58e996fbef7f3/sqlalchemy-2.0.40-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:519624685a51525ddaa7d8ba8265a1540442a2ec71476f0e75241eb8263d6f51", size = 3159542 },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/7e/717eaabaf0f80a0132dc2032ea8f745b7a0914451c984821a7c8737fb75a/sqlalchemy-2.0.40-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2ee5f9999a5b0e9689bed96e60ee53c3384f1a05c2dd8068cc2e8361b0df5b7a", size = 3179864 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/cc/03eb5dfcdb575cbecd2bd82487b9848f250a4b6ecfb4707e834b4ce4ec07/sqlalchemy-2.0.40-cp311-cp311-win32.whl", hash = "sha256:c0cae71e20e3c02c52f6b9e9722bca70e4a90a466d59477822739dc31ac18b4b", size = 2084675 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/48/440946bf9dc4dc231f4f31ef0d316f7135bf41d4b86aaba0c0655150d370/sqlalchemy-2.0.40-cp311-cp311-win_amd64.whl", hash = "sha256:574aea2c54d8f1dd1699449f332c7d9b71c339e04ae50163a3eb5ce4c4325ee4", size = 2110099 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/7c/5fc8e802e7506fe8b55a03a2e1dab156eae205c91bee46305755e086d2e2/sqlalchemy-2.0.40-py3-none-any.whl", hash = "sha256:32587e2e1e359276957e6fe5dad089758bc042a971a8a09ae8ecf7a8fe23d07a", size = 1903894 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sse-starlette"
|
||||
version = "2.2.1"
|
||||
|
||||
Reference in New Issue
Block a user