diff --git a/model/core.js b/model/core.js index be8306a..eb1415b 100644 --- a/model/core.js +++ b/model/core.js @@ -54,6 +54,7 @@ import { QwenApi } from '../utils/alibaba/qwen-api.js' import { BingAIClient } from '../client/CopilotAIClient.js' import Keyv from 'keyv' import crypto from 'crypto' +import {GithubAPITool} from '../utils/tools/GithubTool.js' export const roleMap = { owner: 'group owner', @@ -774,7 +775,8 @@ async function collectTools (e) { new SendMessageToSpecificGroupOrUserTool(), new SendDiceTool(), new QueryGenshinTool(), - new SetTitleTool() + new SetTitleTool(), + new GithubAPITool() ] // todo 3.0再重构tool的插拔和管理 let /** @type{AbstractTool[]} **/ tools = [ @@ -796,7 +798,8 @@ async function collectTools (e) { new APTool(), // new HandleMessageMsgTool(), serpTool, - new QueryUserinfoTool() + new QueryUserinfoTool(), + new GithubAPITool() ] let systemAddition = '' if (e.isGroup) { diff --git a/utils/config.js b/utils/config.js index edba6a4..4c9a9eb 100644 --- a/utils/config.js +++ b/utils/config.js @@ -229,6 +229,8 @@ const defaultConfig = { apiMaxToken: 4096, enableToolPrivateSend: true, // 是否允许智能模式下私聊骚扰其他群友。主人不受影响。 geminiForceToolKeywords: [], + githubAPI: 'https://api.github.com', + githubAPIKey: '', version: 'v2.8.4' } const _path = process.cwd() diff --git a/utils/tools/GithubTool.js b/utils/tools/GithubTool.js new file mode 100644 index 0000000..b110b8c --- /dev/null +++ b/utils/tools/GithubTool.js @@ -0,0 +1,59 @@ +import { AbstractTool } from './AbstractTool.js' +import { Config } from '../config.js' + +export class GithubAPITool extends AbstractTool { + name = 'github' + + parameters = { + properties: { + q: { + type: 'string', + description: 'search keyword' + }, + type: { + type: 'string', + enum: ['repositories', 'issues', 'users', 'code', 'custom'], + description: 'search type. If custom is chosen, you must provide full github api url path.' + }, + num: { + type: 'number', + description: 'search results limit number, default is 5' + }, + fullUrl: { + type: 'string', + description: 'if type is custom, you need provide this, such as /repos/OWNER/REPO/actions/artifacts?name=NAME&page=2&per_page=1' + } + }, + required: ['q', 'type'] + } + + func = async function (opts) { + let { q, type, num = 5, fullUrl = '' } = opts + let headers = { + 'X-From-Library': 'ikechan8370', + Accept: 'application/vnd.github+json' + } + if (Config.githubAPIKey) { + headers.Authorization = `Bearer ${Config.githubAPIKey}` + } + let res + if (type !== 'custom') { + let serpRes = await fetch(`${Config.githubAPI}/search/${type}?q=${encodeURIComponent(q)}&per_page=${num}`, { + headers + }) + serpRes = await serpRes.json() + + res = serpRes.items + } else { + let serpRes = await fetch(`${Config.githubAPI}${fullUrl}`, { + headers + }) + serpRes = await serpRes.json() + res = serpRes.items + } + + return `the search results are here in json format:\n${JSON.stringify(res)} \n(Notice that these information are only available for you, the user cannot see them, you next answer should consider about the information)` + } + + description = 'Useful when you want to search something from api.github.com. You can use preset search types or build your own url path with order, per_page, page and other params.' +}