diff --git a/dashboard/src/lib/plugin-api/marketplace.ts b/dashboard/src/lib/plugin-api/marketplace.ts index d347e1c8..2416827b 100644 --- a/dashboard/src/lib/plugin-api/marketplace.ts +++ b/dashboard/src/lib/plugin-api/marketplace.ts @@ -18,7 +18,7 @@ const PLUGIN_DETAILS_FILE = 'plugin_details.json' * 插件列表 API 响应类型(只包含我们需要的字段) */ interface PluginApiResponse { - id: string + id?: string manifest: { manifest_version: number id?: string @@ -110,7 +110,7 @@ export async function fetchPluginList(): Promise> { console.warn('跳过无效插件数据:', item) return false } - const pluginId = item.manifest.id || item.id + const pluginId = item.manifest.id if (!pluginId) { console.warn('跳过缺少 ID 的插件:', item) return false @@ -122,7 +122,7 @@ export async function fetchPluginList(): Promise> { return true }) .map((item) => ({ - id: item.manifest.id || item.id, + id: item.manifest.id!, manifest: normalizePluginManifest(item.manifest), downloads: 0, rating: 0, diff --git a/prompts/zh-CN/image_description.prompt b/prompts/zh-CN/image_description.prompt index 783daeb1..61bac822 100644 --- a/prompts/zh-CN/image_description.prompt +++ b/prompts/zh-CN/image_description.prompt @@ -1 +1 @@ -请用中文描述这张图片的内容。如果有文字,请把文字描述概括出来,请留意其主题、直观感受,输出为一段平文本,最多30字,请注意不要分点,就输出一段文本 +请用中文详细描述这张图片的内容。如果有文字,请把文字描述概括出来,请留意其主题、直观感受,输出为一段平文本,最多100字,请注意不要分点,就输出一段文本 diff --git a/pytests/webui/test_plugin_management_routes.py b/pytests/webui/test_plugin_management_routes.py index 132cee86..4a3fb011 100644 --- a/pytests/webui/test_plugin_management_routes.py +++ b/pytests/webui/test_plugin_management_routes.py @@ -61,3 +61,76 @@ def test_resolve_installed_plugin_path_accepts_manifest_id_case_mismatch(client: assert plugin_path is not None assert plugin_path.name == "demo_plugin" + + +def test_install_plugin_preserves_manifest_declared_id(client: TestClient, monkeypatch): + class FakeGitMirrorService: + async def clone_repository(self, **kwargs): + target_path = kwargs["target_path"] + target_path.mkdir(parents=True, exist_ok=True) + (target_path / "_manifest.json").write_text( + json.dumps( + { + "manifest_version": 2, + "id": "author.declared", + "name": "Declared Plugin", + "version": "1.0.0", + "author": {"name": "author"}, + } + ), + encoding="utf-8", + ) + return {"success": True} + + monkeypatch.setattr(management_module, "get_git_mirror_service", lambda: FakeGitMirrorService()) + + response = client.post( + "/api/webui/plugins/install", + json={ + "plugin_id": "market.plugin", + "repository_url": "https://github.com/author/declared", + "branch": "main", + }, + ) + + assert response.status_code == 200 + plugin_path = support_module.resolve_installed_plugin_path("author.declared") + assert plugin_path is not None + manifest = json.loads((plugin_path / "_manifest.json").read_text(encoding="utf-8")) + assert manifest["id"] == "author.declared" + + +def test_install_plugin_backfills_missing_manifest_id(client: TestClient, monkeypatch): + class FakeGitMirrorService: + async def clone_repository(self, **kwargs): + target_path = kwargs["target_path"] + target_path.mkdir(parents=True, exist_ok=True) + (target_path / "_manifest.json").write_text( + json.dumps( + { + "manifest_version": 2, + "name": "Legacy Plugin", + "version": "1.0.0", + "author": {"name": "author"}, + } + ), + encoding="utf-8", + ) + return {"success": True} + + monkeypatch.setattr(management_module, "get_git_mirror_service", lambda: FakeGitMirrorService()) + + response = client.post( + "/api/webui/plugins/install", + json={ + "plugin_id": "market.legacy", + "repository_url": "https://github.com/author/legacy", + "branch": "main", + }, + ) + + assert response.status_code == 200 + plugin_path = support_module.resolve_installed_plugin_path("market.legacy") + assert plugin_path is not None + manifest = json.loads((plugin_path / "_manifest.json").read_text(encoding="utf-8")) + assert manifest["id"] == "market.legacy" diff --git a/src/maisaka/builtin_tool/reply.py b/src/maisaka/builtin_tool/reply.py index 65001dd3..a7bb5661 100644 --- a/src/maisaka/builtin_tool/reply.py +++ b/src/maisaka/builtin_tool/reply.py @@ -263,6 +263,7 @@ async def handle_tool( target_user_info = target_message.message_info.user_info target_user_name = target_user_info.user_cardname or target_user_info.user_nickname or target_user_info.user_id + bot_name = config_module.global_config.bot.nickname.strip() or "MaiSaka" if tool_ctx.runtime.chat_stream.platform == CLI_PLATFORM_NAME: tool_ctx.append_guided_reply_to_chat_history(combined_reply_text) @@ -291,7 +292,7 @@ async def handle_tool( ) return tool_ctx.build_success_result( invocation.tool_name, - f'已生成并发送回复"{combined_reply_text}"\n发送对象:{target_user_name}', + f'"{bot_name}"已生成并向"{target_user_name}"发送了回复"{combined_reply_text}"', structured_content={ "msg_id": target_message_id, "set_quote": set_quote, diff --git a/src/webui/routers/plugin/management.py b/src/webui/routers/plugin/management.py index ac38274f..7884831c 100644 --- a/src/webui/routers/plugin/management.py +++ b/src/webui/routers/plugin/management.py @@ -187,9 +187,10 @@ async def install_plugin(request: InstallPluginRequest, maibot_session: Optional for field in ["manifest_version", "name", "version", "author"]: if field not in manifest: raise ValueError(f"缺少必需字段: {field}") - manifest["id"] = plugin_id - with open(manifest_path, "w", encoding="utf-8") as file_obj: - json.dump(manifest, file_obj, ensure_ascii=False, indent=2) + if not str(manifest.get("id", "")).strip(): + manifest["id"] = plugin_id + with open(manifest_path, "w", encoding="utf-8") as file_obj: + json.dump(manifest, file_obj, ensure_ascii=False, indent=2) except Exception as e: remove_tree(target_path) await update_progress( diff --git a/uv.lock b/uv.lock index 2e06f64f..3720e434 100644 --- a/uv.lock +++ b/uv.lock @@ -1511,7 +1511,7 @@ requires-dist = [ { name = "httpx", extras = ["socks"] }, { name = "jieba", specifier = ">=0.42.1" }, { name = "json-repair", specifier = ">=0.47.6" }, - { name = "maibot-dashboard", specifier = ">=1.0.9" }, + { name = "maibot-dashboard", specifier = ">=1.0.10" }, { name = "maibot-plugin-sdk", specifier = ">=2.4.0" }, { name = "maim-message", specifier = ">=0.6.2" }, { name = "matplotlib", specifier = ">=3.10.5" }, @@ -1549,11 +1549,11 @@ dev = [ [[package]] name = "maibot-dashboard" -version = "1.0.9" +version = "1.0.10" source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } -sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/5b/e90896cbdddc89ec5586873de07a3d70c0107e4dc76db8666a0c0fde6ae8/maibot_dashboard-1.0.9.tar.gz", hash = "sha256:0e5c00be021419686105238cded501024f0383a3815bd85f9a1e747f3f04d0cd", size = 2496957, upload-time = "2026-05-07T18:37:51.291Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/b7/3301c49d96bbfde0c61405b7e5afe1c75d625420fdd83d1f4814b9f09eec/maibot_dashboard-1.0.10.tar.gz", hash = "sha256:38be2833f6a17c1f347262eccf5967813327948ad29900b955bb91631844a27c", size = 2496436, upload-time = "2026-05-08T13:15:48.204Z" } wheels = [ - { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/27/ab227a84e55356039004a375e78031e5e8aaf4192e11908a568498816d5e/maibot_dashboard-1.0.9-py3-none-any.whl", hash = "sha256:197b26c5c3d0e6ba1238b91d12c88e57db71c65303cc602fcccdca84ce4db582", size = 2563281, upload-time = "2026-05-07T18:37:49.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/1e/c86f8a98c9de4eef831f855994744ec0512ccfb9322aaef385ca0919f950/maibot_dashboard-1.0.10-py3-none-any.whl", hash = "sha256:749390d6e4c340598e048d72f4c733558163153c0ad4443ff81b5a1c28799629", size = 2563613, upload-time = "2026-05-08T13:15:46.562Z" }, ] [[package]]