perf: display installed plugin icon

This commit is contained in:
Junyan Qin
2025-08-28 23:50:26 +08:00
parent 91959527a4
commit 40f1af4434
5 changed files with 50 additions and 2 deletions

View File

@@ -75,6 +75,20 @@ class PluginsRouterGroup(group.RouterGroup):
return self.success(data={})
@self.route(
'/<author>/<plugin_name>/icon',
methods=['GET'],
auth_type=group.AuthType.NONE,
)
async def _(author: str, plugin_name: str) -> quart.Response:
icon_data = await self.ap.plugin_connector.get_plugin_icon(author, plugin_name)
icon_base64 = icon_data['plugin_icon_base64']
mime_type = icon_data['mime_type']
icon_data = base64.b64decode(icon_base64)
return quart.Response(icon_data, mimetype=mime_type)
@self.route('/install/github', methods=['POST'], auth_type=group.AuthType.USER_TOKEN)
async def _() -> str:
data = await quart.request.json

View File

@@ -7,6 +7,8 @@ import typing
import os
import sys
from async_lru import alru_cache
from ..core import app
from . import handler
from ..utils import platform
@@ -153,6 +155,10 @@ class PluginRuntimeConnector:
async def set_plugin_config(self, plugin_author: str, plugin_name: str, config: dict[str, Any]) -> dict[str, Any]:
return await self.handler.set_plugin_config(plugin_author, plugin_name, config)
@alru_cache(ttl=5 * 60) # 5 minutes
async def get_plugin_icon(self, plugin_author: str, plugin_name: str) -> dict[str, Any]:
return await self.handler.get_plugin_icon(plugin_author, plugin_name)
async def emit_event(
self,
event: events.BaseEventModel,

View File

@@ -534,6 +534,17 @@ class RuntimeConnectionHandler(handler.Handler):
return result['tools']
async def get_plugin_icon(self, plugin_author: str, plugin_name: str) -> dict[str, Any]:
"""Get plugin icon"""
result = await self.call_action(
LangBotToRuntimeAction.GET_PLUGIN_ICON,
{
'plugin_author': plugin_author,
'plugin_name': plugin_name,
},
)
return result
async def call_tool(self, tool_name: str, parameters: dict[str, Any]) -> dict[str, Any]:
"""Call tool"""
result = await self.call_action(

View File

@@ -14,6 +14,7 @@ import {
ArrowUp,
} from 'lucide-react';
import { getCloudServiceClientSync } from '@/app/infra/http';
import { httpClient } from '@/app/infra/http/HttpClient';
import { PluginComponent } from '@/app/infra/entities/plugin';
import { Button } from '@/components/ui/button';
import {
@@ -87,14 +88,19 @@ export default function PluginCardComponent({
onClick={onCardClick}
>
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
<svg
{/* <svg
className="w-16 h-16 text-[#2288ee]"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M8 4C8 2.34315 9.34315 1 11 1C12.6569 1 14 2.34315 14 4C14 4.35064 13.9398 4.68722 13.8293 5H18C18.5523 5 19 5.44772 19 6V10.1707C19.3128 10.0602 19.6494 10 20 10C21.6569 10 23 11.3431 23 13C23 14.6569 21.6569 16 20 16C19.6494 16 19.3128 15.9398 19 15.8293V20C19 20.5523 18.5523 21 18 21H4C3.44772 21 3 20.5523 3 20V6C3 5.44772 3.44772 5 4 5H8.17071C8.06015 4.68722 8 4.35064 8 4Z"></path>
</svg>
</svg> */}
<img
src={httpClient.getPluginIconURL(cardVO.author, cardVO.name)}
alt="plugin icon"
className="w-16 h-16"
/>
<div className="w-full h-full flex flex-col items-start justify-between gap-[0.6rem]">
<div className="flex flex-col items-start justify-start">

View File

@@ -438,6 +438,17 @@ export class BackendClient extends BaseHttpClient {
return this.put(`/api/v1/plugins/${author}/${name}/config`, config);
}
public getPluginIconURL(author: string, name: string): string {
if (this.instance.defaults.baseURL === '/') {
const url = window.location.href;
const baseURL = url.split('/').slice(0, 3).join('/');
return `${baseURL}/api/v1/plugins/${author}/${name}/icon`;
}
return (
this.instance.defaults.baseURL + `/api/v1/plugins/${author}/${name}/icon`
);
}
public installPluginFromGithub(
source: string,
): Promise<AsyncTaskCreatedResp> {