From 3223c82609d5870477a5f92fe20c9b7392e48e80 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Wed, 22 Apr 2026 01:00:34 +0200 Subject: [PATCH 1/5] Add JetBrainsDebugTool --- .../jetbrains/jetbrains_plugin_client.py | 26 ++++++ .../config/internal_modes/jetbrains.yml | 1 + src/serena/tools/jetbrains_tools.py | 79 +++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/src/serena/jetbrains/jetbrains_plugin_client.py b/src/serena/jetbrains/jetbrains_plugin_client.py index d65925ea..61a6a563 100644 --- a/src/serena/jetbrains/jetbrains_plugin_client.py +++ b/src/serena/jetbrains/jetbrains_plugin_client.py @@ -633,6 +633,32 @@ class JetBrainsPluginClient(ToStringMixin): self._postprocess_symbol_collection_response(symbol_collection) return symbol_collection + def debug_eval(self, session_key: str, expression: str) -> dict[str, Any]: + """ + Evaluates a Groovy expression in the persistent debug REPL. + + :param session_key: the session key identifying the REPL instance + :param expression: the Groovy expression to evaluate + :return: the response containing sessionKey and result + """ + request_data = { + "sessionKey": session_key, + "expression": expression, + } + return self._make_request("POST", "/debugEval", request_data) + + def debug_reset(self, session_key: str) -> dict[str, Any]: + """ + Resets the debug REPL for the given session key, clearing all state. + + :param session_key: the session key identifying the REPL instance to reset + :return: the status response + """ + request_data = { + "sessionKey": session_key, + } + return self._make_request("POST", "/debugReset", request_data) + def close(self) -> None: self._session.close() diff --git a/src/serena/resources/config/internal_modes/jetbrains.yml b/src/serena/resources/config/internal_modes/jetbrains.yml index a08b189f..7f76271f 100644 --- a/src/serena/resources/config/internal_modes/jetbrains.yml +++ b/src/serena/resources/config/internal_modes/jetbrains.yml @@ -23,3 +23,4 @@ included_optional_tools: - jet_brains_type_hierarchy - jet_brains_rename - jet_brains_safe_delete + - jet_brains_debug diff --git a/src/serena/tools/jetbrains_tools.py b/src/serena/tools/jetbrains_tools.py index 00d0adbd..dc17009f 100644 --- a/src/serena/tools/jetbrains_tools.py +++ b/src/serena/tools/jetbrains_tools.py @@ -565,3 +565,82 @@ class JetBrainsRenameTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional): rename_in_text_occurrences=rename_in_text_occurrences, ) return self._to_json(result) + + +class JetBrainsDebugTool(Tool, ToolMarkerBeta): + """ + Evaluates Groovy/Java expressions in a persistent debug REPL connected to the JetBrains IDE. + Provides full debugger control: run configs, breakpoints, stepping, inspection, and evaluation. + """ + + def apply( + self, + expression: str, + session_key: str = "default", + ) -> str: + """ + Evaluate a Groovy/Java expression in the persistent debug REPL. State (variables, objects) + persists across calls within the same session_key. + + Pre-bound variables: ``debug`` (DebuggerFacade), ``project`` (IntelliJ Project). + + **Run configurations**:: + + debug.listRunConfigs() + debug.startDebug("MyTestRun") # returns a DebugSession + debug.runConfig("MyApp") # non-debug run, fire-and-forget + + **Session discovery**:: + + debug.sessions() + debug.currentSession() + debug.session(id) + + **Breakpoints** (project-global, set before or during debugging):: + + debug.addBreakpoint(file, line) + debug.addBreakpoint(file, line, condition) + debug.addLogpoint(file, line, logExpression) + debug.listBreakpoints() + debug.removeBreakpointAt(file, line) + + **Execution control** (on a DebugSession, e.g. ``session``):: + + session.stepOver() / .stepInto() / .stepOut() + session.resume() / .pause() / .stop() + session.runToLine(file, line) + + **Wait for pause** (blocks until the session pauses or times out):: + + session.waitForPause(timeoutSeconds) + session.stepOverAndWait(timeoutSeconds) # step + wait in one call + session.resumeAndWait(timeoutSeconds) + + **Inspection**:: + + session.status() # location + source + variables + stack in one call + session.variables() # all locals/args + session.variable(name) # single variable + session.frames() / .frame() # stack trace / current frame + session.sourceContext(lines) # source around current line + session.threads() + + **Evaluation & modification**:: + + session.eval("expr") # evaluate in current frame + session.setVar("x", "42") # set variable via assignment + + **Example**:: + + session = debug.startDebug("MyTest") + debug.addBreakpoint("src/main/java/Foo.java", 42) + session.waitForPause(30) + session.status() + + :param expression: a Groovy/Java expression to evaluate in the REPL + :param session_key: identifies the REPL instance. State persists across calls with the same key. + :return: the string representation of the expression's result + """ + with JetBrainsPluginClient.from_project(self.project) as client: + response = client.debug_eval(session_key=session_key, expression=expression) + return response.get("result", str(response)) From f678d81cac5becb1756164652765e9765daacd89 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Wed, 22 Apr 2026 11:51:22 +0200 Subject: [PATCH 2/5] Improve debugger interface and instructions --- .../jetbrains/jetbrains_plugin_client.py | 20 ++--- src/serena/tools/jetbrains_tools.py | 86 +++++++++++-------- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/serena/jetbrains/jetbrains_plugin_client.py b/src/serena/jetbrains/jetbrains_plugin_client.py index 61a6a563..4987a4ef 100644 --- a/src/serena/jetbrains/jetbrains_plugin_client.py +++ b/src/serena/jetbrains/jetbrains_plugin_client.py @@ -633,31 +633,31 @@ class JetBrainsPluginClient(ToStringMixin): self._postprocess_symbol_collection_response(symbol_collection) return symbol_collection - def debug_eval(self, session_key: str, expression: str) -> dict[str, Any]: + def debug_eval(self, repl_key: str, expression: str) -> dict[str, Any]: """ Evaluates a Groovy expression in the persistent debug REPL. - :param session_key: the session key identifying the REPL instance + :param repl_key: the session key identifying the REPL instance :param expression: the Groovy expression to evaluate - :return: the response containing sessionKey and result + :return: the response containing REPL key and result """ request_data = { - "sessionKey": session_key, + "replKey": repl_key, "expression": expression, } - return self._make_request("POST", "/debugEval", request_data) + return self._make_request("POST", "/debugReplEval", request_data) - def debug_reset(self, session_key: str) -> dict[str, Any]: + def debug_close(self, repl_key: str) -> dict[str, Any]: """ - Resets the debug REPL for the given session key, clearing all state. + Closes the debug REPL for the given session key, clearing all state. - :param session_key: the session key identifying the REPL instance to reset + :param repl_key: the key identifying the REPL instance to close :return: the status response """ request_data = { - "sessionKey": session_key, + "replKey": repl_key, } - return self._make_request("POST", "/debugReset", request_data) + return self._make_request("POST", "/debugReplClose", request_data) def close(self) -> None: self._session.close() diff --git a/src/serena/tools/jetbrains_tools.py b/src/serena/tools/jetbrains_tools.py index dc17009f..58076ddc 100644 --- a/src/serena/tools/jetbrains_tools.py +++ b/src/serena/tools/jetbrains_tools.py @@ -567,80 +567,92 @@ class JetBrainsRenameTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional): return self._to_json(result) -class JetBrainsDebugTool(Tool, ToolMarkerBeta): +class JetBrainsDebugTool(Tool, ToolMarkerOptional, ToolMarkerBeta): """ - Evaluates Groovy/Java expressions in a persistent debug REPL connected to the JetBrains IDE. - Provides full debugger control: run configs, breakpoints, stepping, inspection, and evaluation. + Provides debugging functionality (run configs, breakpoints, stepping, inspection, and evaluation) + via a persistent debug REPL connected to the JetBrains IDE. """ def apply( self, expression: str, - session_key: str = "default", + repl_key: str = "default", ) -> str: """ - Evaluate a Groovy/Java expression in the persistent debug REPL. State (variables, objects) - persists across calls within the same session_key. + Evaluates a Groovy expression in a persistent REPL, which can be used to debug + code interactively. + Important: Debugging should only be applied if the user has requested it! + You rely on the user to provide suitable run configurations for you to work with. - Pre-bound variables: ``debug`` (DebuggerFacade), ``project`` (IntelliJ Project). + Note: The debugger uses 0-based line numbers like other Serena tools (while humans typically communicate 1-based ones). - **Run configurations**:: + State (objects, variables assigned) persists across calls within the same repl_key. + Pre-bound variables: ``debug`` (debugger interface) + + Run configurations: debug.listRunConfigs() - debug.startDebug("MyTestRun") # returns a DebugSession - debug.runConfig("MyApp") # non-debug run, fire-and-forget - - **Session discovery**:: + session = debug.startDebug("MyTestRun") # returns a DebugSession + debug.startRun("MyApp") # non-debug run, fire-and-forget + Session discovery: debug.sessions() - debug.currentSession() - debug.session(id) - - **Breakpoints** (project-global, set before or during debugging):: + session = debug.currentSession() + session = debug.session(id) + Breakpoints (project-global, set before or during debugging): debug.addBreakpoint(file, line) debug.addBreakpoint(file, line, condition) debug.addLogpoint(file, line, logExpression) debug.listBreakpoints() debug.removeBreakpointAt(file, line) - **Execution control** (on a DebugSession, e.g. ``session``):: - - session.stepOver() / .stepInto() / .stepOut() - session.resume() / .pause() / .stop() + Execution control (on a DebugSession, e.g. ``session``):: + session.stepOver() | .stepInto() | .stepOut() + session.resume() | .pause() | .stop() session.runToLine(file, line) - **Wait for pause** (blocks until the session pauses or times out):: - + Wait for pause (blocks until the session pauses or times out): session.waitForPause(timeoutSeconds) session.stepOverAndWait(timeoutSeconds) # step + wait in one call session.resumeAndWait(timeoutSeconds) - **Inspection**:: - - session.status() # location + source + variables + stack in one call - session.variables() # all locals/args - session.variable(name) # single variable - session.frames() / .frame() # stack trace / current frame + Inspection (when paused): + session.status() # location + source + variable values in one call + session.variables() # overview of locals/args (values may be truncated) + session.variable(name) # single variable (VariableInfo instance) + session.frames() | .frame() # stack trace | current frame session.sourceContext(lines) # source around current line session.threads() - **Evaluation & modification**:: + VariableInfo members: name, value (String as presented by the debugger), type - session.eval("expr") # evaluate in current frame + Evaluation & modification: + session.eval("expr") # evaluate in current frame session.setVar("x", "42") # set variable via assignment - **Example**:: - - session = debug.startDebug("MyTest") + Example sequence of expressions one might execute in a REPL: debug.addBreakpoint("src/main/java/Foo.java", 42) + session = debug.startDebug("MyTest") session.waitForPause(30) session.status() - :param expression: a Groovy/Java expression to evaluate in the REPL - :param session_key: identifies the REPL instance. State persists across calls with the same key. - :return: the string representation of the expression's result + You can pass multiple statements at once; the result of the final expression is returned: + session = debug.startDebug("MyTest"); session.waitForPause(30); session.status() + + Control flow statements are also possible: + while (session.variable("count").value.equals("0")) { session.stepOverAndWait(5) } + + When done, close the REPL by passing an empty expression. + + :param expression: a Groovy/Java expression/statement to evaluate in the REPL. + If empty/null, closes the REPL with the given key, discarding its state. + :param repl_key: identifier for the REPL instance. State persists across calls with the same key. + :return: string representation of the result """ with JetBrainsPluginClient.from_project(self.project) as client: - response = client.debug_eval(session_key=session_key, expression=expression) + if expression: + response = client.debug_eval(repl_key=repl_key, expression=expression) + else: + response = client.debug_close(repl_key=repl_key) return response.get("result", str(response)) From b331183c76864a5ab540ee19f6d582ed55e9efce Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 23 Apr 2026 15:53:42 +0200 Subject: [PATCH 3/5] Update documentation to mention JetBrains debug tool --- CHANGELOG.md | 4 +++- README.md | 8 +++++++- docs/02-usage/025_jetbrains_plugin.md | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a9c4006..c467cc96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,9 @@ Status of the `main` branch. Changes prior to the next official version change w The `initial_instructions` tool provides the full prompt on demand, keeping the initial context lean. * JetBrains: - - `Move` and `SafeDelete` tools: transform empty string to None (counteracts client errors) + - Add `debug` tool: The agent can set breakpoints, inspect variables, evaluate expressions and control execution flow + by directly interacting with the IDE's debugger, using a REPL-style interface for maximum flexibility. + - `move` and `safe_delete` tools: transform empty string to None (counteracts client errors) * Dependencies: - `pywebview`: Switch back to official release (new version 6.2) #1253 diff --git a/README.md b/README.md index 7ee19813..0c819fb4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@
-* Serena provides essential **semantic code retrieval, editing and refactoring tools** that are akin to an IDE's capabilities, +* Serena provides essential **semantic code retrieval, editing, refactoring and debugging tools** that are akin to an IDE's capabilities, operating at the symbol level and exploiting relational structure. * It integrates with any client/LLM via the model context protocol (**MCP**). @@ -171,6 +171,12 @@ Serena's symbolic editing tools are less error-prone and much more token-efficie | insert before symbol | yes | yes | | safe delete | yes | yes | +### Interactive Debugging + +Exclusive to the JetBrains plugin, Serena supports a highly general debugging tool, +which allows an agent to set breakpoints, inspect variables, evaluate expressions and control execution flow +via a persistent REPL-style interface. + ### Basic Features Beyond its semantic capabilities, Serena includes a set of basic utilities for completeness. diff --git a/docs/02-usage/025_jetbrains_plugin.md b/docs/02-usage/025_jetbrains_plugin.md index 1995ca34..4eb08688 100644 --- a/docs/02-usage/025_jetbrains_plugin.md +++ b/docs/02-usage/025_jetbrains_plugin.md @@ -43,6 +43,8 @@ There are multiple features that are only available when using the JetBrains plu * **Enhanced retrieval & refactoring capabilities**: The plugin adds additional [tools](../01-about/035_tools) (e.g. type hierarchy retrieval, move, find declaration, inline symbol, etc.) and transforms the underlying mechanisms of shared tools to build upon the IDE's capabilities. +* **Interactive debugging**: The agent can set breakpoints, inspect variables, evaluate expressions and control execution flow + by directly interacting with the IDE's debugger, using a REPL-style interface for maximum flexibility. * **Improved multi-agent support**: A single IDE instance naturally serves arbitrarily many agent sessions without requiring additional resources. * **Enhanced performance**: Faster tool execution thanks to optimized IDE integration. * **Multi-language excellence** and **framework support**: First-class support for polyglot projects with multiple languages. From 3b71b3f306c8287df20cbef3ecc1771f6f2ab329 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 23 Apr 2026 16:14:39 +0200 Subject: [PATCH 4/5] Add version guard for debug tool --- src/serena/jetbrains/jetbrains_plugin_client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serena/jetbrains/jetbrains_plugin_client.py b/src/serena/jetbrains/jetbrains_plugin_client.py index 4987a4ef..263bc8a9 100644 --- a/src/serena/jetbrains/jetbrains_plugin_client.py +++ b/src/serena/jetbrains/jetbrains_plugin_client.py @@ -641,6 +641,7 @@ class JetBrainsPluginClient(ToStringMixin): :param expression: the Groovy expression to evaluate :return: the response containing REPL key and result """ + self._require_version_at_least(2023, 2, 16) request_data = { "replKey": repl_key, "expression": expression, @@ -654,6 +655,7 @@ class JetBrainsPluginClient(ToStringMixin): :param repl_key: the key identifying the REPL instance to close :return: the status response """ + self._require_version_at_least(2023, 2, 16) request_data = { "replKey": repl_key, } From 1fd0fe2cb5b962060d98de4a3e759e0fbd2c4aec Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Fri, 24 Apr 2026 13:44:30 +0200 Subject: [PATCH 5/5] Add SerenaInfoTool for on-demand retrieval of usage information Apply it to provide JetBrains debug REPL information lazily --- CHANGELOG.md | 1 + .../generated/generated_prompt_factory.py | 3 + .../config/internal_modes/jetbrains.yml | 1 + .../config/prompt_templates/info_prompts.yml | 64 ++++++++++++++++++ src/serena/tools/jetbrains_tools.py | 67 +------------------ src/serena/tools/workflow_tools.py | 19 +++++- 6 files changed, 90 insertions(+), 65 deletions(-) create mode 100644 src/serena/resources/config/prompt_templates/info_prompts.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index c467cc96..c6e1ba4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Status of the `main` branch. Changes prior to the next official version change w - Serena's system prompt (a.k.a. the 'Serena Instructions Manual') is now provided lazily. At MCP connection time, only a one-sentence bootstrap prompt is provided. The `initial_instructions` tool provides the full prompt on demand, keeping the initial context lean. + - Add `serena_info` tool for on-demand retrieval of usage information * JetBrains: - Add `debug` tool: The agent can set breakpoints, inspect variables, evaluate expressions and control execution flow diff --git a/src/serena/generated/generated_prompt_factory.py b/src/serena/generated/generated_prompt_factory.py index 58070fd2..43f866d7 100644 --- a/src/serena/generated/generated_prompt_factory.py +++ b/src/serena/generated/generated_prompt_factory.py @@ -14,6 +14,9 @@ class PromptFactory(PromptFactoryBase): A class for retrieving and rendering prompt templates and prompt lists. """ + def create_info_jet_brains_debug_repl(self) -> str: + return self._render_prompt("info_jet_brains_debug_repl", locals()) + def create_onboarding_prompt(self, *, system: Any) -> str: return self._render_prompt("onboarding_prompt", locals()) diff --git a/src/serena/resources/config/internal_modes/jetbrains.yml b/src/serena/resources/config/internal_modes/jetbrains.yml index 7f76271f..34baf6ce 100644 --- a/src/serena/resources/config/internal_modes/jetbrains.yml +++ b/src/serena/resources/config/internal_modes/jetbrains.yml @@ -24,3 +24,4 @@ included_optional_tools: - jet_brains_rename - jet_brains_safe_delete - jet_brains_debug + - serena_info diff --git a/src/serena/resources/config/prompt_templates/info_prompts.yml b/src/serena/resources/config/prompt_templates/info_prompts.yml new file mode 100644 index 00000000..4c896429 --- /dev/null +++ b/src/serena/resources/config/prompt_templates/info_prompts.yml @@ -0,0 +1,64 @@ +# Defines prompts the SerenaInfoTool +prompts: + info_jet_brains_debug_repl: | + Note: The debugger uses 0-based line numbers like other Serena tools (while humans typically communicate 1-based ones). + You rely on the user to provide suitable run configurations for you to work with. + + State (objects, variables assigned) persists across calls within the same repl_key. + + Pre-bound variables: ``debug`` (debugger interface) + + Run configurations: + debug.listRunConfigs() + session = debug.startDebug("MyTestRun") # returns a DebugSession + debug.startRun("MyApp") # non-debug run, fire-and-forget + + Session discovery: + debug.sessions() + session = debug.currentSession() + session = debug.session(id) + + Breakpoints (project-global, set before or during debugging): + debug.addBreakpoint(file, line) + debug.addBreakpoint(file, line, condition) + debug.addLogpoint(file, line, logExpression) + debug.listBreakpoints() + debug.removeBreakpointAt(file, line) + + Execution control (on a DebugSession, e.g. ``session``):: + session.stepOver() | .stepInto() | .stepOut() + session.resume() | .pause() | .stop() + session.runToLine(file, line) + + Wait for pause (blocks until the session pauses or times out): + session.waitForPause(timeoutSeconds) + session.stepOverAndWait(timeoutSeconds) # step + wait in one call + session.resumeAndWait(timeoutSeconds) + + Inspection (when paused): + session.status() # location + source + variable values in one call + session.variables() # overview of locals/args (values may be truncated) + session.variable(name) # single variable (VariableInfo instance) + session.frames() | .frame() # stack trace | current frame + session.sourceContext(lines) # source around current line + session.threads() + + VariableInfo members: name, value (String as presented by the debugger), type + + Evaluation & modification: + session.eval("expr") # evaluate in current frame + session.setVar("x", "42") # set variable via assignment + + Example sequence of expressions one might execute in a REPL: + debug.addBreakpoint("src/main/java/Foo.java", 42) + session = debug.startDebug("MyTest") + session.waitForPause(30) + session.status() + + You can pass multiple statements at once; the result of the final expression is returned: + session = debug.startDebug("MyTest"); session.waitForPause(30); session.status() + + Control flow statements are also possible: + while (session.variable("count").value.equals("0")) { session.stepOverAndWait(5) } + + When done, close the REPL by passing an empty expression. diff --git a/src/serena/tools/jetbrains_tools.py b/src/serena/tools/jetbrains_tools.py index 58076ddc..0664fb03 100644 --- a/src/serena/tools/jetbrains_tools.py +++ b/src/serena/tools/jetbrains_tools.py @@ -579,74 +579,13 @@ class JetBrainsDebugTool(Tool, ToolMarkerOptional, ToolMarkerBeta): repl_key: str = "default", ) -> str: """ - Evaluates a Groovy expression in a persistent REPL, which can be used to debug - code interactively. + Debug code interactively by evaluating Groovy expressions in a persistent REPL. Important: Debugging should only be applied if the user has requested it! - You rely on the user to provide suitable run configurations for you to work with. - Note: The debugger uses 0-based line numbers like other Serena tools (while humans typically communicate 1-based ones). - - State (objects, variables assigned) persists across calls within the same repl_key. - - Pre-bound variables: ``debug`` (debugger interface) - - Run configurations: - debug.listRunConfigs() - session = debug.startDebug("MyTestRun") # returns a DebugSession - debug.startRun("MyApp") # non-debug run, fire-and-forget - - Session discovery: - debug.sessions() - session = debug.currentSession() - session = debug.session(id) - - Breakpoints (project-global, set before or during debugging): - debug.addBreakpoint(file, line) - debug.addBreakpoint(file, line, condition) - debug.addLogpoint(file, line, logExpression) - debug.listBreakpoints() - debug.removeBreakpointAt(file, line) - - Execution control (on a DebugSession, e.g. ``session``):: - session.stepOver() | .stepInto() | .stepOut() - session.resume() | .pause() | .stop() - session.runToLine(file, line) - - Wait for pause (blocks until the session pauses or times out): - session.waitForPause(timeoutSeconds) - session.stepOverAndWait(timeoutSeconds) # step + wait in one call - session.resumeAndWait(timeoutSeconds) - - Inspection (when paused): - session.status() # location + source + variable values in one call - session.variables() # overview of locals/args (values may be truncated) - session.variable(name) # single variable (VariableInfo instance) - session.frames() | .frame() # stack trace | current frame - session.sourceContext(lines) # source around current line - session.threads() - - VariableInfo members: name, value (String as presented by the debugger), type - - Evaluation & modification: - session.eval("expr") # evaluate in current frame - session.setVar("x", "42") # set variable via assignment - - Example sequence of expressions one might execute in a REPL: - debug.addBreakpoint("src/main/java/Foo.java", 42) - session = debug.startDebug("MyTest") - session.waitForPause(30) - session.status() - - You can pass multiple statements at once; the result of the final expression is returned: - session = debug.startDebug("MyTest"); session.waitForPause(30); session.status() - - Control flow statements are also possible: - while (session.variable("count").value.equals("0")) { session.stepOverAndWait(5) } - - When done, close the REPL by passing an empty expression. + Use the `serena_info` tool with topic `jet_brains_debug_repl` for usage information. :param expression: a Groovy/Java expression/statement to evaluate in the REPL. - If empty/null, closes the REPL with the given key, discarding its state. + If empty/null, closes the REPL with the given key. :param repl_key: identifier for the REPL instance. State persists across calls with the same key. :return: string representation of the result """ diff --git a/src/serena/tools/workflow_tools.py b/src/serena/tools/workflow_tools.py index e50ec9b5..461da9ea 100644 --- a/src/serena/tools/workflow_tools.py +++ b/src/serena/tools/workflow_tools.py @@ -4,7 +4,7 @@ Tools supporting the general workflow of the agent import platform -from serena.tools import ReadMemoryTool, Tool, ToolMarkerDoesNotRequireActiveProject, WriteMemoryTool +from serena.tools import ReadMemoryTool, Tool, ToolMarkerDoesNotRequireActiveProject, ToolMarkerOptional, WriteMemoryTool class CheckOnboardingPerformedTool(Tool): @@ -72,3 +72,20 @@ class InitialInstructionsTool(Tool, ToolMarkerDoesNotRequireActiveProject): as it will critically inform you! """ return self.agent.create_system_prompt(session_id=session_id) + + +class SerenaInfoTool(Tool, ToolMarkerOptional, ToolMarkerDoesNotRequireActiveProject): + """ + Provides information about an advanced topic on demand, facilitating context-efficiency. + """ + + def apply(self, topic: str) -> str: + """ + Retrieves Serena-specific information + :param topic: the topic, which you must have been given explicitly + """ + match topic: + case "jet_brains_debug_repl": + return self.agent.prompt_factory.create_info_jet_brains_debug_repl() + case _: + raise ValueError("Invalid topic: " + topic)