c6af9e284a
Tests / catch-all (windows-latest) (push) Has been cancelled
Tests / jvm (macos-latest) (push) Has been cancelled
Tests / jvm (ubuntu-latest) (push) Has been cancelled
Tests / jvm (windows-latest) (push) Has been cancelled
Tests / native (macos-latest) (push) Has been cancelled
Tests / native (ubuntu-latest) (push) Has been cancelled
Tests / native (windows-latest) (push) Has been cancelled
Tests / niche (ubuntu-latest) (push) Has been cancelled
Tests / other-langs (macos-latest) (push) Has been cancelled
Tests / other-langs (ubuntu-latest) (push) Has been cancelled
Tests / other-langs (windows-latest) (push) Has been cancelled
Tests / catch-all (macos-latest) (push) Has been cancelled
Tests / catch-all (ubuntu-latest) (push) Has been cancelled
Docs Build / build (push) Has been cancelled
Docs Build / deploy (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Codespell / Check for spelling errors (push) Has been cancelled
Build and Push Docker Images / build-and-push (push) Has been cancelled
192 lines
6.6 KiB
Python
192 lines
6.6 KiB
Python
"""
|
|
Demonstrates the progressive shortening of tool results when max_answer_chars is exceeded.
|
|
It exercises all tools that use _limit_length with shortened_results,
|
|
printing the full result, then progressively tighter max_answer_chars
|
|
to show the successive shortening stages. Both LSP and JetBrains backends
|
|
are tested (JB is skipped if no IDE is running).
|
|
"""
|
|
|
|
import json
|
|
from pprint import pprint
|
|
|
|
from serena.agent import SerenaAgent
|
|
from serena.config.serena_config import LanguageBackend, SerenaConfig
|
|
from serena.constants import REPO_ROOT
|
|
from serena.tools import (
|
|
FindReferencingSymbolsTool,
|
|
FindSymbolTool,
|
|
GetSymbolsOverviewTool,
|
|
JetBrainsFindReferencingSymbolsTool,
|
|
JetBrainsFindSymbolTool,
|
|
JetBrainsGetSymbolsOverviewTool,
|
|
SearchForPatternTool,
|
|
)
|
|
|
|
SEPARATOR = "=" * 80
|
|
|
|
# symbol with many references across multiple files, good for testing shortening
|
|
REF_SYMBOL = "_limit_length"
|
|
REF_FILE = "src/serena/tools/tools_base.py"
|
|
|
|
# file with many symbols, good for testing overview shortening
|
|
OVERVIEW_FILE = "src/serena/tools/tools_base.py"
|
|
|
|
|
|
def run_with_shrinking(agent: SerenaAgent, label: str, fn, char_limits: list[int]) -> None:
|
|
"""Run a tool call at several max_answer_chars limits and print results."""
|
|
for limit in char_limits:
|
|
tag = f"{label} (max_answer_chars={limit})"
|
|
print(f"\n{SEPARATOR}")
|
|
print(tag)
|
|
print(SEPARATOR)
|
|
result = agent.execute_task(lambda lim=limit: fn(lim))
|
|
n = len(result)
|
|
print(f"[length={n}]")
|
|
try:
|
|
pprint(json.loads(result), width=200)
|
|
except (json.JSONDecodeError, ValueError):
|
|
print(result)
|
|
|
|
|
|
def run_lsp_tools(agent: SerenaAgent) -> None:
|
|
print("\n\n### LSP BACKEND ###\n")
|
|
|
|
# LSP: FindReferencingSymbolsTool — three shortening stages:
|
|
# 1. refs without context lines 2. per-file counts 3. total summary
|
|
lsp_refs = agent.get_tool(FindReferencingSymbolsTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"LSP FindReferencingSymbolsTool",
|
|
lambda lim: lsp_refs.apply(REF_SYMBOL, REF_FILE, max_answer_chars=lim),
|
|
char_limits=[50000, 3000, 500, 200],
|
|
)
|
|
|
|
# LSP: FindSymbolTool — one shortening stage: names with kind only
|
|
lsp_find = agent.get_tool(FindSymbolTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"LSP FindSymbolTool (depth=1)",
|
|
lambda lim: lsp_find.apply("Tool", relative_path=REF_FILE, depth=1, max_answer_chars=lim),
|
|
char_limits=[50000, 200],
|
|
)
|
|
|
|
# LSP: FindSymbolTool with max_matches exceeded — tests the early-return shortened path
|
|
print(f"\n{SEPARATOR}")
|
|
print("LSP FindSymbolTool (max_matches=1, broad search)")
|
|
print(SEPARATOR)
|
|
result = agent.execute_task(lambda: lsp_find.apply("apply", max_matches=1))
|
|
print(f"[length={len(result)}]")
|
|
print(result)
|
|
|
|
# LSP: GetSymbolsOverviewTool — two shortening stages for depth>0:
|
|
# 1. depth-0 overview 2. counts by kind
|
|
# one stage for depth==0: counts by kind
|
|
lsp_overview = agent.get_tool(GetSymbolsOverviewTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"LSP GetSymbolsOverviewTool (depth=1)",
|
|
lambda lim: lsp_overview.apply(OVERVIEW_FILE, depth=1, max_answer_chars=lim),
|
|
char_limits=[50000, 500, 200],
|
|
)
|
|
run_with_shrinking(
|
|
agent,
|
|
"LSP GetSymbolsOverviewTool (depth=0)",
|
|
lambda lim: lsp_overview.apply(OVERVIEW_FILE, depth=0, max_answer_chars=lim),
|
|
char_limits=[50000, 200],
|
|
)
|
|
|
|
|
|
def run_backend_independent_tools(agent: SerenaAgent) -> None:
|
|
print("\n\n### BACKEND-INDEPENDENT TOOLS ###\n")
|
|
|
|
# SearchForPatternTool — three shortening stages:
|
|
# 1. match lines per file (no context) 2. match counts per file 3. total summary
|
|
search_tool = agent.get_tool(SearchForPatternTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"SearchForPatternTool (with context)",
|
|
lambda lim: search_tool.apply(
|
|
"_limit_length",
|
|
context_lines_before=1,
|
|
context_lines_after=1,
|
|
relative_path="src/serena/tools",
|
|
max_answer_chars=lim,
|
|
),
|
|
char_limits=[50000, 1000, 200],
|
|
)
|
|
|
|
|
|
def run_jb_tools(agent: SerenaAgent) -> None:
|
|
print("\n\n### JETBRAINS BACKEND ###\n")
|
|
|
|
# JB: FindReferencingSymbolsTool — two shortening stages:
|
|
# 1. per-file counts 2. total summary
|
|
jb_refs = agent.get_tool(JetBrainsFindReferencingSymbolsTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"JB FindReferencingSymbolsTool",
|
|
lambda lim: jb_refs.apply(REF_SYMBOL, REF_FILE, max_answer_chars=lim),
|
|
char_limits=[50000, 500, 200],
|
|
)
|
|
|
|
# JB: FindSymbolTool — one shortening stage: names with kind only
|
|
jb_find = agent.get_tool(JetBrainsFindSymbolTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"JB FindSymbolTool (depth=1)",
|
|
lambda lim: jb_find.apply("Tool", relative_path=REF_FILE, depth=1, max_answer_chars=lim),
|
|
char_limits=[50000, 200],
|
|
)
|
|
|
|
# JB: FindSymbolTool with max_matches exceeded — tests the early-return shortened path
|
|
print(f"\n{SEPARATOR}")
|
|
print("JB FindSymbolTool (max_matches=1, broad search)")
|
|
print(SEPARATOR)
|
|
result = agent.execute_task(lambda: jb_find.apply("apply", max_matches=1))
|
|
print(f"[length={len(result)}]")
|
|
print(result)
|
|
|
|
# JB: GetSymbolsOverviewTool — two shortening stages for depth>0:
|
|
# 1. depth-0 overview 2. counts by type
|
|
# two stages for depth==0: grouped symbols, then counts by type
|
|
jb_overview = agent.get_tool(JetBrainsGetSymbolsOverviewTool)
|
|
run_with_shrinking(
|
|
agent,
|
|
"JB GetSymbolsOverviewTool (depth=1)",
|
|
lambda lim: jb_overview.apply(OVERVIEW_FILE, depth=1, max_answer_chars=lim),
|
|
char_limits=[50000, 500, 200],
|
|
)
|
|
run_with_shrinking(
|
|
agent,
|
|
"JB GetSymbolsOverviewTool (depth=0)",
|
|
lambda lim: jb_overview.apply(OVERVIEW_FILE, depth=0, max_answer_chars=lim),
|
|
char_limits=[50000, 200],
|
|
)
|
|
|
|
|
|
def make_agent(backend: LanguageBackend) -> SerenaAgent:
|
|
config = SerenaConfig.from_config_file()
|
|
config.web_dashboard = False
|
|
config.language_backend = backend
|
|
return SerenaAgent(project=REPO_ROOT, serena_config=config)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# LSP backend
|
|
lsp_agent = make_agent(LanguageBackend.LSP)
|
|
try:
|
|
run_lsp_tools(lsp_agent)
|
|
run_backend_independent_tools(lsp_agent)
|
|
finally:
|
|
lsp_agent.on_shutdown()
|
|
|
|
# JetBrains backend (requires a running IDE)
|
|
try:
|
|
jb_agent = make_agent(LanguageBackend.JETBRAINS)
|
|
try:
|
|
run_jb_tools(jb_agent)
|
|
finally:
|
|
jb_agent.on_shutdown()
|
|
except Exception as e:
|
|
print(f"\nJetBrains backend not available, skipping: {e}")
|