feat: Add LLM Provider support in plugin runtime
- Introduced LLM Provider declarations in plugin manifests, allowing plugins to specify their LLM capabilities. - Implemented validation for LLM Provider declarations to prevent duplicates and conflicts. - Enhanced the PluginRunner to handle LLM Provider invocation requests, enabling plugins to interact with LLM Providers seamlessly. - Added a ClientRegistry to manage LLM Provider registrations and ensure no conflicts arise between different plugins. - Created a PluginLLMClient to facilitate communication with LLM Providers through the plugin runtime. - Developed tests to ensure proper registration and conflict handling of LLM Providers.
This commit is contained in:
@@ -148,6 +148,35 @@ class PluginRuntimeManager(
|
||||
validator = ManifestValidator(validate_python_package_dependencies=False)
|
||||
return validator.build_plugin_dependency_map(plugin_dirs)
|
||||
|
||||
@classmethod
|
||||
def _discover_llm_provider_conflicts(cls, plugin_dirs: Iterable[Path]) -> Dict[str, str]:
|
||||
"""扫描插件 Manifest,发现 LLM Provider client_type 冲突。
|
||||
|
||||
Args:
|
||||
plugin_dirs: 需要扫描的插件根目录集合。
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: 需要阻止加载的插件 ID 与原因映射。
|
||||
"""
|
||||
validator = ManifestValidator(validate_python_package_dependencies=False)
|
||||
provider_owners: Dict[str, List[str]] = {}
|
||||
for _plugin_path, manifest in validator.iter_plugin_manifests(plugin_dirs, require_entrypoint=True):
|
||||
for client_type in manifest.llm_provider_client_types:
|
||||
provider_owners.setdefault(client_type, []).append(manifest.id)
|
||||
|
||||
blocked_reasons: Dict[str, str] = {}
|
||||
for client_type, plugin_ids in provider_owners.items():
|
||||
unique_plugin_ids = sorted(set(plugin_ids))
|
||||
if len(unique_plugin_ids) <= 1:
|
||||
continue
|
||||
reason = (
|
||||
f"LLM Provider client_type 冲突: {client_type} 被以下插件重复声明: "
|
||||
f"{', '.join(unique_plugin_ids)}"
|
||||
)
|
||||
for plugin_id in unique_plugin_ids:
|
||||
blocked_reasons[plugin_id] = reason
|
||||
return blocked_reasons
|
||||
|
||||
@classmethod
|
||||
def _build_group_start_order(
|
||||
cls,
|
||||
@@ -271,7 +300,11 @@ class PluginRuntimeManager(
|
||||
"""
|
||||
|
||||
result = await self._plugin_dependency_pipeline.execute(plugin_dirs)
|
||||
changed_plugin_ids = self._set_blocked_plugin_reasons(result.blocked_plugin_reasons)
|
||||
blocked_plugin_reasons = {
|
||||
**result.blocked_plugin_reasons,
|
||||
**self._discover_llm_provider_conflicts(plugin_dirs),
|
||||
}
|
||||
changed_plugin_ids = self._set_blocked_plugin_reasons(blocked_plugin_reasons)
|
||||
return DependencySyncState(
|
||||
blocked_changed_plugin_ids=changed_plugin_ids,
|
||||
environment_changed=result.environment_changed,
|
||||
|
||||
Reference in New Issue
Block a user