fix(plugin): share the runtime file-transfer root and 404 uninstalled icon requests

The SDK binds one transfer root inode (mode 0700) and picks it per profile: a shared worker uses /tmp/lbp-rpc while a host without the profile env fell back to data/temp/lbp, so plugin icons and assets died with 'Invalid file transfer capability'. The host now pins the shared root, and a plugin absent from the resolved Workspace answers 404 instead of 500.
This commit is contained in:
Hyu
2026-10-02 01:34:47 +08:00
parent 38d5750785
commit 34b5fe0202
2 changed files with 70 additions and 1 deletions
@@ -165,6 +165,16 @@ except Exception:
pass
def _is_plugin_not_installed(exc: BaseException) -> bool:
"""True when the connector reports a plugin absent from the resolved Workspace.
The connector raises a plain ``ValueError`` for this case, so resource routes
answer 404 instead of surfacing a 500 the WebUI would have to swallow.
"""
return 'is not installed in this workspace' in str(exc).lower()
def _normalize_plugin_asset_path(filepath: str) -> str | None:
filepath = filepath.replace('\\', '/')
if filepath.startswith('/'):
@@ -596,7 +606,15 @@ class PluginsRouterGroup(group.RouterGroup):
request_context: RequestContext,
) -> quart.Response:
await self._require_authenticated_plugin_runtime_context(request_context)
icon_data = await self.ap.plugin_connector.get_plugin_icon(author, plugin_name)
try:
icon_data = await self.ap.plugin_connector.get_plugin_icon(author, plugin_name)
except ValueError as exc:
# A plugin that is not installed for this Workspace is a missing
# resource, not a server fault: the WebUI asks for icons by plugin
# identity and must be able to fall back silently.
if _is_plugin_not_installed(exc):
return quart.Response('Icon not found', status=404)
raise
icon_bytes = await asyncio.to_thread(base64.b64decode, icon_data['plugin_icon_base64'])
return quart.Response(icon_bytes, mimetype=icon_data['mime_type'])