diff --git a/.gitignore b/.gitignore index d3304dd0..2dd6d7d9 100755 --- a/.gitignore +++ b/.gitignore @@ -184,4 +184,7 @@ praises.json # vitepress and node.js node_modules/ docs/.vitepress/cache -docs/.vitepress/dist \ No newline at end of file +docs/.vitepress/dist + +# viztracer +result.json \ No newline at end of file diff --git a/nonebot_plugin_marshoai/plugin/__init__.py b/nonebot_plugin_marshoai/plugin/__init__.py index bffca6f8..d7096de1 100644 --- a/nonebot_plugin_marshoai/plugin/__init__.py +++ b/nonebot_plugin_marshoai/plugin/__init__.py @@ -1,8 +1,6 @@ """该功能目前~~正在开发中~~开发基本完成,暂时~~不~~可用,受影响的文件夹 `plugin`, `plugins` """ -from nonebot import logger - from .func_call import * from .load import * from .models import * diff --git a/nonebot_plugin_marshoai/plugin/func_call/caller.py b/nonebot_plugin_marshoai/plugin/func_call/caller.py index 41b73505..c8c090b7 100644 --- a/nonebot_plugin_marshoai/plugin/func_call/caller.py +++ b/nonebot_plugin_marshoai/plugin/func_call/caller.py @@ -39,12 +39,12 @@ class Caller: if self.bot is None or self.event is None: return False, "Context is None" if self._permission and not await self._permission(self.bot, self.event): - return False, "Permission Denied 权限不足" + return False, "告诉用户 Permission Denied 权限不足" if self.state is None: return False, "State is None" if self._rule and not await self._rule(self.bot, self.event, self.state): - return False, "Rule Denied 规则不匹配" + return False, "告诉用户 Rule Denied 规则不匹配" return True, "" @@ -92,10 +92,10 @@ class Caller: self.func = async_wrap(func) # type: ignore if module := inspect.getmodule(func): - module_name = module.__name__ + "." + module_name = module.__name__.split(".")[-1] + "." else: module_name = "" - logger.opt(colors=True).info( + logger.opt(colors=True).debug( f"加载函数 {module_name}{func.__name__}: {self._description}" ) diff --git a/nonebot_plugin_marshoai/plugin/load.py b/nonebot_plugin_marshoai/plugin/load.py index 7f2a5d5f..895c94e3 100755 --- a/nonebot_plugin_marshoai/plugin/load.py +++ b/nonebot_plugin_marshoai/plugin/load.py @@ -19,6 +19,8 @@ _plugins: dict[str, Plugin] = {} __all__ = [ "load_plugin", "load_plugins", + "get_plugin", + "get_plugins", "_plugins", ] diff --git a/nonebot_plugin_marshoai/plugins/builtin_tools/__init__.py b/nonebot_plugin_marshoai/plugins/builtin_tools/__init__.py new file mode 100644 index 00000000..57a5fba6 --- /dev/null +++ b/nonebot_plugin_marshoai/plugins/builtin_tools/__init__.py @@ -0,0 +1,12 @@ +from nonebot_plugin_marshoai.plugin import PluginMetadata + +from .file_io import * +from .manager import * +from .network import * + +__marsho_meta__ = PluginMetadata( + name="内置增强组件", + version="0.0.1", + description="内置工具插件", + author="MarshoTeam of LiteyukiStudio", +) diff --git a/nonebot_plugin_marshoai/plugins/builtin_tools/file_io.py b/nonebot_plugin_marshoai/plugins/builtin_tools/file_io.py new file mode 100644 index 00000000..4ee2c748 --- /dev/null +++ b/nonebot_plugin_marshoai/plugins/builtin_tools/file_io.py @@ -0,0 +1,23 @@ +import aiofiles # type: ignore +from nonebot.permission import SUPERUSER + +from nonebot_plugin_marshoai.plugin import String, on_function_call + + +@on_function_call(description="获取设备上本地文件内容").params( + fp=String(description="文件路径") +).permission(SUPERUSER) +async def read_file(fp: str) -> str: + """获取设备上本地文件内容 + + Args: + fp (str): 文件路径 + + Returns: + str: 文件内容 + """ + try: + async with aiofiles.open(fp, "r", encoding="utf-8") as f: + return await f.read() + except Exception as e: + return "读取出错: " + str(e) diff --git a/nonebot_plugin_marshoai/plugins/builtin_tools/manager.py b/nonebot_plugin_marshoai/plugins/builtin_tools/manager.py new file mode 100644 index 00000000..d45e1067 --- /dev/null +++ b/nonebot_plugin_marshoai/plugins/builtin_tools/manager.py @@ -0,0 +1,18 @@ +from nonebot_plugin_marshoai.plugin import get_plugins, on_function_call + + +@on_function_call(description="获取已加载的插件列表") +def get_marsho_plugins() -> str: + """获取已加载的插件列表 + + Returns: + str: 插件列表 + """ + + reply = "加载的插件列表" + for p in get_plugins().values(): + if p.metadata: + reply += f"名称: {p.metadata.name},描述: {p.metadata.description}\n" + else: + reply += f"名称: {p.name},描述: 暂无\n" + return reply diff --git a/nonebot_plugin_marshoai/plugins/builtin_tools/network.py b/nonebot_plugin_marshoai/plugins/builtin_tools/network.py new file mode 100644 index 00000000..3dd8a907 --- /dev/null +++ b/nonebot_plugin_marshoai/plugins/builtin_tools/network.py @@ -0,0 +1,48 @@ +import time + +from httpx import AsyncClient +from newspaper import Article +from nonebot import logger + +from nonebot_plugin_marshoai.plugin.func_call.caller import on_function_call +from nonebot_plugin_marshoai.plugin.func_call.params import String + +headers = { + "User-Agent": "Firefox/90.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" +} + + +@on_function_call( + description="使用网页链接(url)获取网页内容摘要,可以让AI上网查询资料" +).params( + url=String(description="网页链接"), + typ=String(description="获取类型,摘要还是内容", enum=["摘要", "内容"]), +) +async def get_web_content(url: str, typ: str) -> str: + """使用网页链接获取网页内容摘要 + 为什么要获取摘要,不然token超限了 + + Args: + url (str): _description_ + + Returns: + str: _description_ + """ + async with AsyncClient(headers=headers) as client: + try: + response = await client.get(url) + t1 = time.time() + article = Article(url) + article.set_html(response.text) + article.parse() + t2 = time.time() + logger.debug(f"获取网页内容耗时: {t2 - t1}") + if typ == "摘要": + return f"标题: {article.title}\n作者: {article.authors}\n发布日期: {article.publish_date}" + elif typ == "内容": + return f"标题: {article.title}\n作者: {article.authors}\n发布日期: {article.publish_date}\n摘要: {article.summary}\n正文: {article.text}" + except Exception as e: + logger.error(f"marsho builtin: 获取网页内容失败: {e}") + return "获取网页内容失败:" + str(e) + + return "未能获取到有效的网页内容" diff --git a/nonebot_plugin_marshoai/plugins/builtin_tools/utils.py b/nonebot_plugin_marshoai/plugins/builtin_tools/utils.py new file mode 100644 index 00000000..e69de29b diff --git a/pyproject.toml b/pyproject.toml index 56a87a56..7e830466 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,10 @@ dependencies = [ "psutil>=6.1.0", "beautifulsoup4>=4.12.3", "pydantic>=2.10.3", - "litedoc>=0.1.0.dev20241214103915" + "litedoc>=0.1.0.dev20241214103915", + "newspaper3k>=0.2.8", + "lxml[html_clean]>=5.3.0", + "aiofiles>=24.1.0" ] license = { text = "MIT, Mulan PSL v2" } @@ -65,6 +68,7 @@ dev = [ "mypy>=1.13.0", "black>=24.10.0", "litedoc>=0.1.0.dev20240906203154", + "viztracer>=1.0.0", ] test = [ "nonebug>=0.4.3",