Skip to content

Commit 76056dc

Browse files
committed
Combine get_definition and get_type_and_docs tool calls
Usually you don't want just one, so better to give the information all at once. Especially since some models, like o3-mini, are sparse with their tool calls.
1 parent 8172ccc commit 76056dc

File tree

2 files changed

+30
-37
lines changed

2 files changed

+30
-37
lines changed

optastic/chat.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@
1414

1515
from optastic.project import Project
1616
from optastic.tools import (
17+
GetInfoTool,
1718
GetReferencesTool,
1819
GetSurroundingCodeTool,
19-
GetTypeAndDocsTool,
2020
LLMToolRunner,
21-
GetDefinitionTool,
2221
)
2322

2423

@@ -48,9 +47,8 @@ def run_chat(project: Project, filename: str, lineno: int, model_id: str):
4847
tool_runner = LLMToolRunner(
4948
project,
5049
[
51-
GetDefinitionTool(),
50+
GetInfoTool(),
5251
GetReferencesTool(),
53-
GetTypeAndDocsTool(),
5452
GetSurroundingCodeTool(),
5553
],
5654
)

optastic/tools.py

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ def exec(self, req: dict, project: Project) -> Any:
2121
pass
2222

2323

24-
class GetDefinitionTool(LLMTool):
24+
class GetInfoTool(LLMTool):
2525
class Model(BaseModel):
2626
filename: str = Field(description="The filename")
2727
line: int = Field(description="The 1-based line number")
2828
symbol: str = Field(description="The symbol's text")
2929

3030
schema = openai.pydantic_function_tool(
3131
Model,
32-
name="get_definition",
33-
description="Get the definition (including source code) of a symbol at a particular location",
32+
name="get_info",
33+
description="Get the definition (including source code), type, and docs of a symbol at a particular location",
3434
)
3535

3636
def exec(self, req: dict, project: Project) -> Any:
@@ -51,7 +51,16 @@ def exec(self, req: dict, project: Project) -> Any:
5151
),
5252
)
5353
return list(
54-
map(lambda r: add_src_to_loc(convert_lsp_loc(r, project), project), resp)
54+
map(
55+
lambda e: add_info_to_loc(
56+
add_src_to_loc(convert_lsp_loc(e, project), project),
57+
project,
58+
r.filename,
59+
line,
60+
column,
61+
),
62+
resp,
63+
)
5564
)
5665

5766

@@ -126,37 +135,23 @@ def add_src_to_loc(loc: dict, p: Project) -> dict:
126135
return loc
127136

128137

129-
class GetTypeAndDocsTool(LLMTool):
130-
class Model(BaseModel):
131-
filename: str = Field(description="The filename")
132-
line: int = Field(description="The 1-based line number")
133-
symbol: str = Field(description="The symbol's text")
134-
135-
schema = openai.pydantic_function_tool(
136-
Model,
137-
name="get_type_and_docs",
138-
description="Get info (like inferred types and documentation) about a code symbol at a particular location",
139-
)
140-
141-
def exec(self, req: dict, project: Project) -> Any:
142-
r = self.Model.model_validate(req)
138+
def add_info_to_loc(
139+
loc: dict, p: Project, filename: str, line: int, column: int
140+
) -> dict:
141+
info = get_hover(p, filename, line, column)
142+
loc["info"] = info
143+
return loc
143144

144-
srclines = project.get_lines(r.filename)
145-
result = find_symbol(srclines, r.line - 1, r.symbol)
146-
if result is None:
147-
return {
148-
"error": "symbol {r.symbol} not found at {r.filename}:{r.line} (wrong line number?)"
149-
}
150-
line, column = result["line_idx"], result["end_chr"]
151145

152-
resp = project.lsp().request_hover(r.filename, line, column)
153-
if resp is None:
154-
return {"error": "no info found for that location (wrong line number?)"}
155-
if type(resp["contents"]) is dict and "kind" in resp["contents"]:
156-
contents = resp["contents"]["value"]
157-
else:
158-
raise Exception(f"unsupported textDocument/hover response: {resp}")
159-
return truncate_for_llm(contents, 1000)
146+
def get_hover(project: Project, filename: str, line: int, column: int):
147+
resp = project.lsp().request_hover(filename, line, column)
148+
if resp is None:
149+
return None
150+
if type(resp["contents"]) is dict and "kind" in resp["contents"]:
151+
contents = resp["contents"]["value"]
152+
else:
153+
raise Exception(f"unsupported textDocument/hover response: {resp}")
154+
return truncate_for_llm(contents, 1000)
160155

161156

162157
class GetSurroundingCodeTool(LLMTool):

0 commit comments

Comments
 (0)