Skip to content

Commit ea56a00

Browse files
authored
feat: implement codeSearch functionality (#4629)
1 parent 30d9244 commit ea56a00

File tree

2 files changed

+69
-10
lines changed

2 files changed

+69
-10
lines changed

servers/fai-lambda/fai-code-indexing/src/handler.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,23 @@ def handler(event: dict[str, Any], context: Any) -> dict[str, Any]:
3535
repo_urls = validate_body_param_or_throw(body, "repoUrls", list[str])
3636
asyncio.run(setup_repos_for_domain(domain=domain, repo_urls=repo_urls))
3737

38-
message = f"Successfully indexed {len(repo_urls)} repositories"
38+
response_body = {
39+
"message": f"Successfully indexed {len(repo_urls)} repositories",
40+
"timestamp": datetime.now(UTC).isoformat(),
41+
"requestId": context.aws_request_id,
42+
}
43+
3944
elif event_type == "codeSearch":
40-
asyncio.run(run_code_search_tool_call(domain=domain))
41-
message = "Code search completed successfully"
45+
question = validate_body_param_or_throw(body, "question")
46+
session_id = body.get("sessionId")
47+
result = asyncio.run(run_code_search_tool_call(domain=domain, question=question, session_id=session_id))
4248

43-
response_body = {
44-
"message": message,
45-
"timestamp": datetime.now(UTC).isoformat(),
46-
"requestId": context.aws_request_id,
47-
}
49+
response_body = {
50+
"message": "Code search completed successfully",
51+
"timestamp": datetime.now(UTC).isoformat(),
52+
"requestId": context.aws_request_id,
53+
"answer": result.get("answer", None),
54+
}
4855

4956
return {
5057
"statusCode": 200,

servers/fai-lambda/fai-code-indexing/src/operations/search.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,35 @@
11
import logging
2+
import os
3+
from pathlib import Path
24
from typing import Any
35

6+
from claude_agent_sdk import (
7+
AssistantMessage,
8+
ClaudeAgentOptions,
9+
TextBlock,
10+
ToolUseBlock,
11+
query,
12+
)
13+
414
logger = logging.getLogger()
515

616

7-
async def run_code_search_tool_call(domain: str) -> dict[str, Any]:
17+
CLAUDE_ANSWER_CODE_QUESTION_USER_PROMPT = """
18+
You are given a question who's answer might lie in one of the code repositories and your job is to answer it.
19+
20+
Process:
21+
- Analyze the question and determine which repository or repositories are relevant to the question.
22+
- Use the relevant repositories to answer the question to the best of your ability.
23+
24+
Guidelines:
25+
- Keep answers as concise as possible while providing all the necessary details to unblock the user.
26+
- Be sure to provide a balance of code examples and text explanations to keep answers engaging and easy to follow.
27+
- Refrain from providing `full working examples` (only snippets/excerpts to support text steps)
28+
29+
Question: {question}
30+
"""
31+
32+
async def run_code_search_tool_call(domain: str, question: str, session_id: str | None = None) -> dict[str, Any]:
833
"""Run a code search tool call for a domain.
934
1035
Args:
@@ -15,9 +40,36 @@ async def run_code_search_tool_call(domain: str) -> dict[str, Any]:
1540
"""
1641
logger.info(f"Running code search for domain: {domain}")
1742

18-
# TODO: Implement code search logic
43+
efs_root = Path(os.environ.get("HOME", "/mnt/efs"))
44+
domain_folder = efs_root / domain
45+
46+
answer = None
47+
48+
async for message in query(
49+
prompt=CLAUDE_ANSWER_CODE_QUESTION_USER_PROMPT.format(question=question),
50+
options=ClaudeAgentOptions(
51+
cwd=str(domain_folder),
52+
disallowed_tools=["Write", "Delete", "Rename"],
53+
resume=session_id,
54+
fork_session=True
55+
)
56+
):
57+
if hasattr(message, 'subtype') and message.subtype == 'init':
58+
session_id = message.data.get('session_id')
59+
print(f"Session started with ID: {session_id}")
60+
61+
if isinstance(message, AssistantMessage):
62+
for content in message.content:
63+
if isinstance(content, ToolUseBlock):
64+
print(f"Tool used: {content.name}")
65+
print(f"Tool input: {content.input}")
66+
if isinstance(content, TextBlock):
67+
print(f"Text: {content.text}")
68+
answer = content.text
69+
1970

2071
return {
2172
"domain": domain,
2273
"status": "success",
74+
"answer": answer,
2375
}

0 commit comments

Comments
 (0)