Skip to content

Commit e7637c8

Browse files
committed
feat: Implement web-search and url-fetch tools
1 parent 1a31e6e commit e7637c8

4 files changed

Lines changed: 94 additions & 3 deletions

File tree

build.sbt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ lazy val root = project
1616
"io.circe" %% "circe-generic" % "0.14.5",
1717
"io.circe" %% "circe-parser" % "0.14.5",
1818
"org.jline" % "jline" % "3.21.0",
19-
"com.github.scopt" %% "scopt" % "4.1.0"
19+
"com.github.scopt" %% "scopt" % "4.1.0",
20+
"com.lihaoyi" %% "requests" % "0.8.0",
21+
"com.lihaoyi" %% "upickle" % "3.1.2"
2022
)
2123
)
2224

src/main/scala/com/supercoder/agents/CoderAgent.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.supercoder.agents
22

33
import com.openai.models.FunctionDefinition
44
import com.supercoder.base.{BaseChatAgent, ToolCallDescription}
5-
import com.supercoder.tools.{CodeEditTool, CommandExecutionTool, CodeSearchTool, FileReadTool, ProjectStructureTool}
5+
import com.supercoder.tools.{CodeEditTool, CodeSearchTool, CommandExecutionTool, FileReadTool, ProjectStructureTool, UrlFetchTool, WebSearchTool}
66

77
val coderAgentPrompt = s"""
88
You are a senior software engineer AI agent. Your task is to help the user with their coding needs.
@@ -14,9 +14,14 @@ You have access to the following tools:
1414
- ${FileReadTool.functionDefinition.name}: ${FileReadTool.functionDefinition.description}
1515
- ${CodeEditTool.functionDefinition.name}: ${CodeEditTool.functionDefinition.description}
1616
- ${CommandExecutionTool.functionDefinition.name}: ${CommandExecutionTool.functionDefinition.description}
17+
- ${UrlFetchTool.functionDefinition.name}: ${UrlFetchTool.functionDefinition.description}
18+
- ${WebSearchTool.functionDefinition.name}: ${WebSearchTool.functionDefinition.description}
1719

1820
You can use these tools to help you with the user's request.
1921

22+
When using the web-search tool, make sure you also use the url-fetch tool to read the content of the result URLs if needed.
23+
24+
2025
The discussion is about the code of the current project/folder. Always use the relevant tool to learn about the
2126
project if you are unsure before giving answer.
2227
"""
@@ -29,7 +34,9 @@ class CoderAgent(additionalPrompt: String = "", model: String = "")
2934
ProjectStructureTool,
3035
FileReadTool,
3136
CodeEditTool,
32-
CommandExecutionTool
37+
CommandExecutionTool,
38+
UrlFetchTool,
39+
WebSearchTool
3340
)
3441

3542
override def toolDefinitionList: List[FunctionDefinition] =
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.supercoder.tools
2+
3+
import com.openai.models.FunctionDefinition
4+
import com.supercoder.base.Tool
5+
import com.supercoder.lib.Console.green
6+
import io.circe.*
7+
import io.circe.generic.auto.*
8+
import io.circe.parser.*
9+
10+
case class UrlFetchToolArguments(url: String)
11+
12+
object UrlFetchTool extends Tool {
13+
override val functionDefinition: FunctionDefinition = FunctionDefinition.builder()
14+
.name("url-fetch")
15+
.description("Fetch content from a specified URL. Arguments: {\"url\": \"<target-url>\"}")
16+
.build()
17+
18+
override def execute(arguments: String): String = {
19+
val parsedArguments = decode[UrlFetchToolArguments](arguments)
20+
parsedArguments match {
21+
case Right(args) =>
22+
val url = args.url
23+
println(green(s"\uD83D\uDD0D Fetching URL: $url"))
24+
try {
25+
val response = requests.get(
26+
url,
27+
connectTimeout = 5000,
28+
readTimeout = 10000
29+
)
30+
response.text()
31+
} catch {
32+
case e: Exception => s"Error: ${e.getMessage}"
33+
}
34+
case Left(error) =>
35+
s"Error: Invalid arguments - ${error.getMessage}"
36+
}
37+
}
38+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.supercoder.tools
2+
3+
import com.openai.models.FunctionDefinition
4+
import com.supercoder.base.Tool
5+
import com.supercoder.lib.Console.green
6+
import io.circe.*
7+
import io.circe.generic.auto.*
8+
import io.circe.parser.*
9+
10+
import java.net.URLEncoder
11+
12+
case class WebSearchToolArguments(query: String, limit: Int)
13+
14+
object WebSearchTool extends Tool {
15+
val searxngInstance: String = sys.env.getOrElse("SEARXNG_URL", "")
16+
17+
override val functionDefinition: FunctionDefinition = FunctionDefinition.builder()
18+
.name("web-search")
19+
.description("Perform web search using SearxNG. Use this when you need to find information that is not in the codebase or when you need to find a specific library or tool. Arguments: {\"query\": \"<search-query>\", \"limit\": <max-results>}")
20+
.build()
21+
22+
override def execute(arguments: String): String = {
23+
if (searxngInstance.isEmpty) {
24+
return "Error: SearxNG instance URL is not set. Please set the SEARXNG_URL environment variable."
25+
}
26+
val parsedArguments = decode[WebSearchToolArguments](arguments)
27+
parsedArguments match {
28+
case Right(args) =>
29+
val query = args.query
30+
val encodedQuery = URLEncoder.encode(args.query, "UTF-8")
31+
val limit = args.limit
32+
println(green(s"🔍 Searching the web for: $query"))
33+
try {
34+
val searchUrl = s"$searxngInstance/search?q=$encodedQuery&format=json&limit=$limit"
35+
val response = requests.get(searchUrl)
36+
response.text()
37+
} catch {
38+
case e: Exception => s"Error: ${e.getMessage}"
39+
}
40+
case Left(error) =>
41+
s"Error: Invalid arguments - ${error.getMessage}"
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)