mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-12 18:16:43 +00:00
Add SerenaInfoTool for on-demand retrieval of usage information
Apply it to provide JetBrains debug REPL information lazily
This commit is contained in:
1 parent
3b71b3f306
commit
1fd0fe2cb5
6 files changed
+90
-65
No files matched your search
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -24,3 +24,4 @@ included_optional_tools:
|
||||
- jet_brains_rename
|
||||
- jet_brains_safe_delete
|
||||
- jet_brains_debug
|
||||
- serena_info
|
||||
@@ -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.
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user