From be465a7bd7ad6b8044bb4e1547b616925c370629 Mon Sep 17 00:00:00 2001 From: jie65535 Date: Tue, 24 Dec 2024 23:16:14 +0800 Subject: [PATCH] Add glot run code agent --- src/main/kotlin/JChatGPT.kt | 12 +++- src/main/kotlin/PluginConfig.kt | 4 ++ src/main/kotlin/tools/RunCode.kt | 107 +++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/tools/RunCode.kt diff --git a/src/main/kotlin/JChatGPT.kt b/src/main/kotlin/JChatGPT.kt index 40ec76d..10f1a75 100644 --- a/src/main/kotlin/JChatGPT.kt +++ b/src/main/kotlin/JChatGPT.kt @@ -327,10 +327,20 @@ object JChatGPT : KotlinPlugin( * 工具列表 */ private val myTools = listOf( + // 网页搜索 WebSearch(), + + // 运行代码 + RunCode(), + + // 天气服务 WeatherService(), - CrazyKfc(), + + // IP所在地查询 IpAddressQuery(), + + // 疯狂星期四 + CrazyKfc(), ) diff --git a/src/main/kotlin/PluginConfig.kt b/src/main/kotlin/PluginConfig.kt index 908a189..0c63be6 100644 --- a/src/main/kotlin/PluginConfig.kt +++ b/src/main/kotlin/PluginConfig.kt @@ -31,4 +31,8 @@ object PluginConfig : AutoSavePluginConfig("Config") { @ValueDescription("SearXNG 搜索引擎地址,如 http://127.0.0.1:8080/search 必须启用允许json格式返回") val searXngUrl: String by value("") + + @ValueDescription("在线运行代码 glot.io 的 api token,在官网注册账号即可获取。") + val glotToken: String by value("") + } \ No newline at end of file diff --git a/src/main/kotlin/tools/RunCode.kt b/src/main/kotlin/tools/RunCode.kt new file mode 100644 index 0000000..614442c --- /dev/null +++ b/src/main/kotlin/tools/RunCode.kt @@ -0,0 +1,107 @@ +package top.jie65535.mirai.tools + +import com.aallam.openai.api.chat.Tool +import com.aallam.openai.api.core.Parameters +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import kotlinx.serialization.json.* +import top.jie65535.mirai.PluginConfig + +class RunCode : BaseAgent( + tool = Tool.function( + name = "runCode", + description = "执行代码,请尽量避免需要运行时输入或可能导致死循环的代码!", + parameters = Parameters.buildJsonObject { + put("type", "object") + putJsonObject("properties") { + putJsonObject("language") { + put("type", "string") + putJsonArray("enum") { + GLOT_LANGUAGES.forEach(::add) + } + } + putJsonObject("files") { + put("type", "array") + putJsonObject("items") { + put("type", "object") + putJsonObject("file") { + putJsonObject("name") { + put("type", "string") + put("description", "文件名,如 main.py") + } + putJsonObject("content") { + put("type", "string") + put("description", "文件内容,如 print(42)") + } + } + } + put("description", "代码文件") + } + putJsonObject("stdin") { + put("type", "string") + put("description", "可选的标准输入内容") + } + } + putJsonArray("required") { + add("language") + add("files") + } + } + ) +) { + companion object { + /** + * Glot API 地址 + */ + const val GLOT_RUN_API_URL = "https://glot.io/api/run/" + + /** + * 使用的语言版本 仅有最新 + */ + const val GLOT_LANGUAGE_VERSION = "/latest" + + /** + * Glot支持的编程语言(经过过滤和排序,实际支持40+,没必要) + */ + val GLOT_LANGUAGES = listOf( + "bash", + "python", + "c", + "cpp", + "csharp", + "kotlin", + "java", + "javascript", + "typescript", + "go", + "rust", + "lua", + ) + } + + /** + * 设置了Token以后才启用 + */ + override val isEnabled: Boolean + get() = PluginConfig.glotToken.isNotEmpty() + + override val loadingMessage: String + get() = "执行代码中..." + + override suspend fun execute(args: JsonObject?): String { + requireNotNull(args) + val language = args.getValue("language").jsonPrimitive.content + val filteredArgs = args.toMutableMap().let { + it.remove("language") + JsonObject(it) + } + val url = GLOT_RUN_API_URL + language + GLOT_LANGUAGE_VERSION + val response = httpClient.post(url) { + contentType(ContentType("application", "json")) + header("Authorization", PluginConfig.glotToken) + setBody(filteredArgs.toString()) + } + return response.bodyAsText() + } +} \ No newline at end of file