feat(runner): filter marketplace recommendations by explicit usage

This commit is contained in:
RockChinQ
2026-09-12 12:51:16 +08:00
parent fa15f48fd7
commit 1277c6da07
28 changed files with 272 additions and 23 deletions
@@ -32,6 +32,7 @@ def make_descriptor(
permissions: dict | None = None,
) -> RunnerDescriptor:
return RunnerDescriptor(
usages=['agent'],
id='plugin:test/runner/default',
source='plugin',
label={'en_US': 'Test Runner'},
@@ -91,6 +91,7 @@ class TestContextValidation:
def _make_descriptor(self):
"""Create a mock runner descriptor."""
return RunnerDescriptor(
usages=['agent'],
id='plugin:test/plugin/runner',
source='plugin',
label={'en_US': 'Test Runner'},
@@ -125,6 +125,7 @@ class MockApplication:
class FakeRunnerRegistry:
async def get(self, context, runner_id, bound_plugins=None):
return RunnerDescriptor(
usages=['agent'],
id=runner_id,
source='plugin',
label={'en_US': 'Test Runner'},
@@ -23,6 +23,7 @@ SOURCE = {'source': 'native', 'source_id': None}
async def _resources(tool_mgr, rag_mgr, binding):
descriptor = RunnerDescriptor(
usages=['agent'],
id=LOCAL_RUNNER_ID,
source='plugin',
label={'en_US': 'Local Agent'},
@@ -164,6 +164,7 @@ class FakeConversation:
def make_descriptor() -> RunnerDescriptor:
return RunnerDescriptor(
usages=['agent'],
id=RUNNER_ID,
source='plugin',
label={'en_US': 'Local Agent'},
+19
View File
@@ -55,6 +55,7 @@ class FakeApplication:
'id': 'plugin:langbot-team/LocalAgent/default',
'name': 'default',
'label': {'en_US': 'Local Agent'},
'usages': ['agent'],
'capabilities': {'streaming': True},
'permissions': {},
'config_schema': [],
@@ -68,6 +69,7 @@ class FakeApplication:
'id': 'plugin:alice/my-agent/custom',
'name': 'custom',
'label': {'en_US': 'Custom Agent'},
'usages': ['agent'],
'capabilities': {},
'permissions': {},
'config_schema': [{'name': 'param1', 'type': 'string'}],
@@ -308,6 +310,7 @@ class TestDescriptorValidation:
def test_validate_runner_descriptor(self):
"""Validate correctly built descriptor."""
descriptor = RunnerDescriptor(
usages=['agent'],
id='plugin:test/my-runner/default',
source='plugin',
label={'en_US': 'Test Runner'},
@@ -323,6 +326,7 @@ class TestDescriptorValidation:
def test_descriptor_capabilities(self):
"""Descriptor capability helper methods."""
descriptor = RunnerDescriptor(
usages=['agent'],
id='plugin:test/my-runner/default',
source='plugin',
label={'en_US': 'Test Runner'},
@@ -365,3 +369,18 @@ async def test_registry_filters_usages_without_splitting_component_identity():
assert [item.runner_name for item in processors] == ['events', 'both']
assert agents[-1].id == processors[-1].id
assert (await registry.get(TEST_CONTEXT, processors[0].id)).usages == ['event']
@pytest.mark.asyncio
async def test_discovery_rejects_runner_without_usage_declaration():
ap = FakeApplication()
original = ap.plugin_connector.list_runners
async def missing_usage(bound_plugins=None):
runners = await original(bound_plugins)
runners[0]['manifest'].pop('usages')
return runners
ap.plugin_connector.list_runners = missing_usage
runners = await RunnerRegistry(ap).list_runners(TEST_CONTEXT, use_cache=False)
assert [runner.id for runner in runners] == ['plugin:alice/my-agent/custom']
@@ -39,6 +39,7 @@ def make_descriptor(
permissions: dict | None = None,
) -> RunnerDescriptor:
return RunnerDescriptor(
usages=['agent'],
id=RUNNER_ID,
source='plugin',
label={'en_US': 'Test Runner'},
@@ -37,6 +37,7 @@ class FakeApplication:
def make_descriptor():
"""Create a test descriptor."""
return RunnerDescriptor(
usages=['agent'],
id='plugin:langbot-team/LocalAgent/default',
source='plugin',
label={'en_US': 'Local Agent', 'zh_Hans': '内置 Agent'},
@@ -25,6 +25,7 @@ from langbot.pkg.agent.runner.state_scope import (
def make_descriptor(runner_id: str = 'plugin:test/my-runner/default') -> RunnerDescriptor:
"""Create a test descriptor."""
return RunnerDescriptor(
usages=['agent'],
id=runner_id,
source='plugin',
label={'en_US': 'Test Runner'},