feat: trace plugin installation

This commit is contained in:
Junyan Qin
2025-08-16 15:42:49 +08:00
parent 288b294148
commit 5179b3e53a
10 changed files with 167 additions and 152 deletions
+2
View File
@@ -13,6 +13,8 @@ class PluginSetting(Base):
enabled = sqlalchemy.Column(sqlalchemy.Boolean, nullable=False, default=True)
priority = sqlalchemy.Column(sqlalchemy.Integer, nullable=False, default=0)
config = sqlalchemy.Column(sqlalchemy.JSON, nullable=False, default=dict)
install_source = sqlalchemy.Column(sqlalchemy.String(255), nullable=False, default='github')
install_info = sqlalchemy.Column(sqlalchemy.JSON, nullable=False, default=dict)
created_at = sqlalchemy.Column(sqlalchemy.DateTime, nullable=False, server_default=sqlalchemy.func.now())
updated_at = sqlalchemy.Column(
sqlalchemy.DateTime,
@@ -0,0 +1,25 @@
import sqlalchemy
from .. import migration
@migration.migration_class(5)
class DBMigratePluginInstallSource(migration.DBMigration):
"""插件安装来源"""
async def upgrade(self):
"""升级"""
# add new column install_source, use default value 'github', via alter table
await self.ap.persistence_mgr.execute_async(
sqlalchemy.text(
"ALTER TABLE plugin_settings ADD COLUMN install_source VARCHAR(255) NOT NULL DEFAULT 'github'"
)
)
# add new column install_info, use default value {}, via alter table
await self.ap.persistence_mgr.execute_async(
sqlalchemy.text("ALTER TABLE plugin_settings ADD COLUMN install_info JSON NOT NULL DEFAULT '{}'")
)
async def downgrade(self):
"""降级"""
pass
+10 -1
View File
@@ -105,7 +105,16 @@ class PluginRuntimeConnector:
install_info: dict[str, Any],
task_context: taskmgr.TaskContext | None = None,
):
return await self.handler.install_plugin(install_source.value, install_info)
async for ret in self.handler.install_plugin(install_source.value, install_info):
current_action = ret.get('current_action', None)
if current_action is not None:
if task_context is not None:
task_context.set_current_action(current_action)
trace = ret.get('trace', None)
if trace is not None:
if task_context is not None:
task_context.trace(trace)
async def list_plugins(self) -> list[dict[str, Any]]:
return await self.handler.list_plugins()
+49 -3
View File
@@ -39,6 +39,43 @@ class RuntimeConnectionHandler(handler.Handler):
super().__init__(connection, disconnect_callback)
self.ap = ap
@self.action(RuntimeToLangBotAction.INITIALIZE_PLUGIN_SETTINGS)
async def initialize_plugin_settings(data: dict[str, Any]) -> handler.ActionResponse:
"""Initialize plugin settings"""
# check if exists plugin setting
plugin_author = data['plugin_author']
plugin_name = data['plugin_name']
install_source = data['install_source']
install_info = data['install_info']
result = await self.ap.persistence_mgr.execute_async(
sqlalchemy.select(persistence_plugin.PluginSetting)
.where(persistence_plugin.PluginSetting.plugin_author == plugin_author)
.where(persistence_plugin.PluginSetting.plugin_name == plugin_name)
)
if result.first() is not None:
# delete plugin setting
await self.ap.persistence_mgr.execute_async(
sqlalchemy.delete(persistence_plugin.PluginSetting)
.where(persistence_plugin.PluginSetting.plugin_author == plugin_author)
.where(persistence_plugin.PluginSetting.plugin_name == plugin_name)
)
# create plugin setting
await self.ap.persistence_mgr.execute_async(
sqlalchemy.insert(persistence_plugin.PluginSetting).values(
plugin_author=plugin_author,
plugin_name=plugin_name,
install_source=install_source,
install_info=install_info,
)
)
return handler.ActionResponse.success(
data={},
)
@self.action(RuntimeToLangBotAction.GET_PLUGIN_SETTINGS)
async def get_plugin_settings(data: dict[str, Any]) -> handler.ActionResponse:
"""Get plugin settings"""
@@ -56,6 +93,8 @@ class RuntimeConnectionHandler(handler.Handler):
'enabled': False,
'priority': 0,
'plugin_config': {},
'install_source': 'local',
'install_info': {},
}
setting = result.first()
@@ -64,6 +103,8 @@ class RuntimeConnectionHandler(handler.Handler):
data['enabled'] = setting.enabled
data['priority'] = setting.priority
data['plugin_config'] = setting.config
data['install_source'] = setting.install_source
data['install_info'] = setting.install_info
return handler.ActionResponse.success(
data=data,
@@ -373,17 +414,22 @@ class RuntimeConnectionHandler(handler.Handler):
timeout=10,
)
async def install_plugin(self, install_source: str, install_info: dict[str, Any]) -> dict[str, Any]:
async def install_plugin(
self, install_source: str, install_info: dict[str, Any]
) -> typing.AsyncGenerator[dict[str, Any], None]:
"""Install plugin"""
return await self.call_action(
gen = self.call_action_generator(
LangBotToRuntimeAction.INSTALL_PLUGIN,
{
'install_source': install_source,
'install_info': install_info,
},
timeout=10,
timeout=120,
)
async for ret in gen:
yield ret
async def list_plugins(self) -> list[dict[str, Any]]:
"""List plugins"""
result = await self.call_action(
+1 -1
View File
@@ -1,6 +1,6 @@
semantic_version = 'v4.0.7'
required_database_version = 4
required_database_version = 5
"""标记本版本所需要的数据库结构版本,用于判断数据库迁移"""
debug_mode = False