feat(agent-runner): integrate AgentRunner Protocol v1 with plugin system

Phase 0 integration complete - verified minimal loop with local-agent stub runner.

Changes:
- Add AgentRunOrchestrator for plugin-based agent execution
- Add AgentResultNormalizer for Protocol v1 result conversion
- Add AgentRunnerDescriptor for runner ID parsing (plugin:author/name/runner)
- Update chat handler to use new orchestrator instead of direct runner lookup
- Add plugin handler methods for list_agent_runners and run_agent
- Add connector methods for AgentRunner protocol forwarding
- Update pipeline API to include runner options in metadata
- Add integration docs and implementation plan

Integration verified:
- Runner: plugin:langbot/local-agent/default
- Input: "你好"
- Output: [stub] Echo: 你好
- Date: 2026-05-10 10:09

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
huanghuoguoguo
2026-05-10 10:11:54 +08:00
parent b01294b005
commit d6b8f48e73
29 changed files with 3960 additions and 289 deletions

View File

@@ -779,14 +779,16 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
yield cmd_ret
# AgentRunner methods
async def list_agent_runners(self, bound_plugins: list[str] | None = None) -> list[ComponentManifest]:
"""List all available AgentRunner components."""
async def list_agent_runners(self, bound_plugins: list[str] | None = None) -> list[dict[str, Any]]:
"""List all available AgentRunner components.
Returns list of dicts with plugin_author, plugin_name, runner_name, manifest, etc.
"""
if not self.is_enable_plugin:
return []
runners_data = await self.handler.list_agent_runners(include_plugins=bound_plugins)
runners = [ComponentManifest.model_validate(runner) for runner in runners_data]
return runners
return runners_data
async def run_agent(
self,
@@ -804,10 +806,18 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
context: AgentRunContext as dict
Yields:
AgentRunReturn results as dicts
AgentRunResult dicts per Protocol v1
"""
if not self.is_enable_plugin:
yield {'type': 'finish', 'finish_reason': 'error', 'content': 'Plugin system is disabled'}
# Return v1 protocol run.failed
yield {
'type': 'run.failed',
'data': {
'error': 'Plugin system is disabled',
'code': 'plugin.disabled',
'retryable': False,
},
}
return
gen = self.handler.run_agent(plugin_author, plugin_name, runner_name, context)