feat(runner): unify plugin execution across agents and event processors

This commit is contained in:
RockChinQ
2026-09-10 18:04:38 +08:00
parent 8903a40c41
commit f24a7c9bb2
223 changed files with 4090 additions and 3067 deletions
+17 -17
View File
@@ -26,7 +26,7 @@ class _RuntimeActionName:
AGENT_RUN_ADMIN_PERMISSION = 'agent_run:admin'
RUNTIME_ADMIN_PERMISSION = 'runtime:admin'
AGENT_RUNNER_ADMIN_PERMISSION = 'agent_runner:admin'
RUNNER_ADMIN_PERMISSION = 'runner:admin'
LEDGER_ONLY_SIDE_EFFECTING_RESULT_TYPES = {
'message.delta',
'message.completed',
@@ -50,15 +50,15 @@ def _normalize_permission_set(value: Any) -> set[str]:
return set()
def _iter_agent_runner_admin_plugin_configs(ap: app.Application) -> list[dict[str, Any]]:
def _iter_runner_admin_plugin_configs(ap: app.Application) -> list[dict[str, Any]]:
instance_config = getattr(ap, 'instance_config', None)
config_data = getattr(instance_config, 'data', {}) if instance_config is not None else {}
if not isinstance(config_data, dict):
return []
agent_runner_config = config_data.get('agent_runner', {})
if not isinstance(agent_runner_config, dict):
runner_config = config_data.get('runner', {})
if not isinstance(runner_config, dict):
return []
raw_admin_plugins = agent_runner_config.get('admin_plugins', [])
raw_admin_plugins = runner_config.get('admin_plugins', [])
if isinstance(raw_admin_plugins, dict):
items: list[dict[str, Any]] = []
for identity, entry in raw_admin_plugins.items():
@@ -74,12 +74,12 @@ def _iter_agent_runner_admin_plugin_configs(ap: app.Application) -> list[dict[st
return []
def _agent_runner_admin_permissions(ap: app.Application, plugin_identity: str | None) -> set[str]:
def _runner_admin_permissions(ap: app.Application, plugin_identity: str | None) -> set[str]:
if not isinstance(plugin_identity, str) or not plugin_identity.strip():
return set()
normalized_identity = plugin_identity.strip()
permissions: set[str] = set()
for entry in _iter_agent_runner_admin_plugin_configs(ap):
for entry in _iter_runner_admin_plugin_configs(ap):
if entry.get('enabled', True) is False:
continue
identity = entry.get('identity') or entry.get('plugin_identity') or entry.get('plugin') or entry.get('id')
@@ -90,19 +90,19 @@ def _agent_runner_admin_permissions(ap: app.Application, plugin_identity: str |
return permissions
def _has_agent_runner_admin_permission(
def _has_runner_admin_permission(
ap: app.Application,
plugin_identity: str | None,
permission: str,
) -> bool:
permissions = _agent_runner_admin_permissions(ap, plugin_identity)
permissions = _runner_admin_permissions(ap, plugin_identity)
if not permissions:
return False
domain = permission.split(':', 1)[0]
return bool(
permission in permissions
or f'{domain}:*' in permissions
or AGENT_RUNNER_ADMIN_PERMISSION in permissions
or RUNNER_ADMIN_PERMISSION in permissions
or '*' in permissions
)
@@ -251,11 +251,11 @@ async def _validate_agent_run_session(
allow_persistent_authorization: bool = False,
admin_permission: str | None = None,
) -> Union[tuple[None, handler.ActionResponse], tuple[Any, None]]:
"""Validate an AgentRunner pull API run session and run-scoped API access."""
"""Validate an Runner pull API run session and run-scoped API access."""
if (
not run_id
and admin_permission
and _has_agent_runner_admin_permission(
and _has_runner_admin_permission(
ap,
caller_plugin_identity,
admin_permission,
@@ -294,7 +294,7 @@ async def _validate_agent_run_session(
if api_capability:
available_apis = _get_run_authorization(session).get('available_apis', {})
has_admin_permission = bool(admin_permission) and _has_agent_runner_admin_permission(
has_admin_permission = bool(admin_permission) and _has_runner_admin_permission(
ap,
caller_plugin_identity,
admin_permission,
@@ -428,7 +428,7 @@ def _project_event_record_for_api(event: dict[str, Any]) -> dict[str, Any]:
def _project_runner_descriptor_for_api(descriptor: Any) -> dict[str, Any]:
"""Project an AgentRunnerDescriptor-like object onto a JSON dict."""
"""Project an RunnerDescriptor-like object onto a JSON dict."""
if isinstance(descriptor, dict):
return dict(descriptor)
if hasattr(descriptor, 'model_dump'):
@@ -449,7 +449,7 @@ def _project_runner_descriptor_for_api(descriptor: Any) -> dict[str, Any]:
}
async def _record_agent_runner_admin_action(
async def _record_runner_admin_action(
ap: app.Application,
store: Any,
*,
@@ -460,7 +460,7 @@ async def _record_agent_runner_admin_action(
target_runtime_id: str | None = None,
detail: dict[str, Any] | None = None,
) -> None:
"""Record a small audit trail for privileged AgentRunner operations."""
"""Record a small audit trail for privileged Runner operations."""
audit_data: dict[str, Any] = {
'action': action,
'caller_plugin_identity': caller_plugin_identity,
@@ -485,4 +485,4 @@ async def _record_agent_runner_admin_action(
metadata={'permission': permission},
)
except Exception as exc:
ap.logger.warning(f'Failed to record AgentRunner admin audit event: {exc}', exc_info=True)
ap.logger.warning(f'Failed to record Runner admin audit event: {exc}', exc_info=True)
@@ -71,7 +71,7 @@ def register(h):
await store.append_event(
event_id=None,
event_type='steering.injected',
source='agent_runner',
source='runner',
bot_id=conversation.get('bot_id') if isinstance(conversation, dict) else None,
workspace_id=conversation.get('workspace_id') if isinstance(conversation, dict) else None,
conversation_id=conversation.get('conversation_id') if isinstance(conversation, dict) else None,
+15 -15
View File
@@ -1094,8 +1094,8 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
async def initialize_plugins(self):
pass
async def _refresh_agent_runner_registry(self) -> None:
registry = getattr(self.ap, 'agent_runner_registry', None)
async def _refresh_runner_registry(self) -> None:
registry = getattr(self.ap, 'runner_registry', None)
if registry is None:
return
try:
@@ -1814,7 +1814,7 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
if task_context is not None:
task_context.set_current_action('refreshing plugin components')
task_context.metadata['progress_percent'] = 95
await self._refresh_agent_runner_registry()
await self._refresh_runner_registry()
if task_context is not None:
operation = task_context.metadata.get('operation')
task_context.set_current_action('plugin updated' if operation == 'upgrade' else 'plugin installed')
@@ -1903,7 +1903,7 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
self._workspace_installations.pop(binding.workspace_uuid, None)
if task_context is not None:
task_context.set_current_action('plugin removed')
await self._refresh_agent_runner_registry()
await self._refresh_runner_registry()
return {}
async def list_plugins(self, component_kinds: list[str] | None = None) -> list[dict[str, Any]]:
@@ -2245,9 +2245,9 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
async for ret in gen:
yield command_context.CommandReturn.model_validate(ret)
# AgentRunner methods
async def list_agent_runners(self, bound_plugins: list[str] | None = None) -> list[dict[str, Any]]:
"""List all available AgentRunner components.
# Runner methods
async def list_runners(self, bound_plugins: list[str] | None = None) -> list[dict[str, Any]]:
"""List all available Runner components.
Returns list of dicts with plugin_author, plugin_name, runner_name, manifest, etc.
"""
@@ -2260,26 +2260,26 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
runners: list[dict[str, Any]] = []
for binding in await self._operation_bindings(include_plugins=bound_plugins):
with runtime_handler.installation_scope(binding):
runners.extend(await runtime_handler.list_agent_runners(include_plugins=bound_plugins))
runners.extend(await runtime_handler.list_runners(include_plugins=bound_plugins))
return runners
async def run_agent(
async def run_runner(
self,
plugin_author: str,
plugin_name: str,
runner_name: str,
context: dict[str, Any],
) -> typing.AsyncGenerator[dict[str, Any], None]:
"""Run an AgentRunner from a plugin.
"""Run an Runner from a plugin.
Args:
plugin_author: Plugin author
plugin_name: Plugin name
runner_name: AgentRunner component name
context: AgentRunContext as dict
runner_name: Runner component name
context: RunnerContext as dict
Yields:
AgentRunResult dicts
RunnerResult dicts
"""
if not self.is_enable_plugin:
# Return a protocol-level failure result.
@@ -2297,7 +2297,7 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
'metadata', {}
).get('workspace_id')
if not isinstance(workspace_id, str) or not workspace_id.strip():
raise ValueError('AgentRunner execution requires a Workspace')
raise ValueError('Runner execution requires a Workspace')
execution_context = await self._current_execution_context()
if workspace_id.strip() != execution_context.workspace_uuid:
raise WorkspaceNotFoundError('Plugin resource not found')
@@ -2309,7 +2309,7 @@ class PluginRuntimeConnector(ManagedRuntimeConnector):
)
runtime_handler = self._runtime_handler()
with runtime_handler.installation_scope(binding):
async for ret in runtime_handler.run_agent(
async for ret in runtime_handler.run_runner(
plugin_author,
plugin_name,
runner_name,
+37 -37
View File
@@ -56,7 +56,7 @@ from ..agent.runner.platform_tools import execute_platform_tool, get_platform_to
from ..pipeline.pool import get_query_execution_context
from . import agent_pull_actions, agent_runner_actions, agent_state_actions
from . import agent_pull_actions, runner_actions, agent_state_actions
from .agent_run_support import (
_validate_agent_run_session,
)
@@ -177,7 +177,7 @@ async def _get_pipeline_knowledge_base_uuids(ap: app.Application, query: Any) ->
return []
runner_config = RunnerConfigResolver.resolve_runner_config(pipeline_config, runner_id)
registry = getattr(ap, 'agent_runner_registry', None)
registry = getattr(ap, 'runner_registry', None)
if registry is None:
return []
@@ -189,7 +189,7 @@ async def _get_pipeline_knowledge_base_uuids(ap: app.Application, query: Any) ->
bound_plugins,
)
except Exception as e:
ap.logger.warning(f'Failed to load AgentRunner descriptor for knowledge-base scope: {e}')
ap.logger.warning(f'Failed to load Runner descriptor for knowledge-base scope: {e}')
return []
return config_schema.extract_knowledge_base_uuids(descriptor, runner_config)
@@ -1275,7 +1275,7 @@ class RuntimeConnectionHandler(handler.Handler):
async def count_tokens(data: dict[str, Any]) -> handler.ActionResponse:
"""Count model input tokens.
For AgentRunner calls: requires run_id and validates model_uuid against session.resources.models.
For Runner calls: requires run_id and validates model_uuid against session.resources.models.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
"""
action_context, _ = await self._require_plugin_action_context()
@@ -1338,7 +1338,7 @@ class RuntimeConnectionHandler(handler.Handler):
async def invoke_llm(data: dict[str, Any]) -> handler.ActionResponse:
"""Invoke llm
For AgentRunner calls: requires run_id and validates model_uuid against session.resources.models.
For Runner calls: requires run_id and validates model_uuid against session.resources.models.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
"""
action_context, _ = await self._require_plugin_action_context()
@@ -1346,11 +1346,11 @@ class RuntimeConnectionHandler(handler.Handler):
messages = data['messages']
funcs = data.get('funcs', [])
extra_args = data.get('extra_args', {})
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
session = None
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'model', llm_model_uuid, self.ap, caller_plugin_identity, operation='invoke'
@@ -1431,7 +1431,7 @@ class RuntimeConnectionHandler(handler.Handler):
async def invoke_llm_stream(data: dict[str, Any]):
"""Invoke llm with streaming response
For AgentRunner calls: requires run_id and validates model_uuid against session.resources.models.
For Runner calls: requires run_id and validates model_uuid against session.resources.models.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
"""
action_context, _ = await self._require_plugin_action_context()
@@ -1439,11 +1439,11 @@ class RuntimeConnectionHandler(handler.Handler):
messages = data['messages']
funcs = data.get('funcs', [])
extra_args = data.get('extra_args', {})
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
session = None
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'model', llm_model_uuid, self.ap, caller_plugin_identity, operation='stream'
@@ -1565,27 +1565,27 @@ class RuntimeConnectionHandler(handler.Handler):
async def call_tool(data: dict[str, Any]) -> handler.ActionResponse:
"""Call a tool
For AgentRunner calls: requires run_id and validates tool_name against session.resources.tools.
For Runner calls: requires run_id and validates tool_name against session.resources.tools.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
"""
tool_name = data['tool_name']
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
session = None
source_ref = None
is_agent_runner_call = bool(run_id)
is_runner_call = bool(run_id)
action_context = self._require_runtime_action_context()
if is_agent_runner_call:
if is_runner_call:
if 'parameters' not in data:
return handler.ActionResponse.error(
message='parameters is required for AgentRunner tool calls',
message='parameters is required for Runner tool calls',
)
parameters = data.get('parameters') or {}
else:
parameters = data.get('tool_parameters') or {}
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'tool', tool_name, self.ap, caller_plugin_identity, operation='call'
@@ -1627,7 +1627,7 @@ class RuntimeConnectionHandler(handler.Handler):
result = await self.ap.tool_mgr.execute_func_call(
**execute_kwargs,
)
if is_agent_runner_call:
if is_runner_call:
return handler.ActionResponse.success(data={'result': result})
return handler.ActionResponse.success(data={'tool_response': result})
except Exception as e:
@@ -1640,19 +1640,19 @@ class RuntimeConnectionHandler(handler.Handler):
async def get_tool_detail(data: dict[str, Any]) -> handler.ActionResponse:
"""Get tool detail for LLM function calling.
For AgentRunner calls: requires run_id and validates tool_name against session.resources.tools.
For Runner calls: requires run_id and validates tool_name against session.resources.tools.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
Returns tool manifest including name, description, and parameters schema.
"""
tool_name = data['tool_name']
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
session = None
source_ref = None
action_context = self._require_runtime_action_context()
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'tool', tool_name, self.ap, caller_plugin_identity, operation='detail'
@@ -1693,10 +1693,10 @@ class RuntimeConnectionHandler(handler.Handler):
# ================= Binary Storage Handlers =================
# Permission validation:
# - For AgentRunner calls (with run_id): validates storage permission via session_registry
# - For Runner calls (with run_id): validates storage permission via session_registry
# - For regular plugin calls (no run_id): unrestricted access (backward compatibility)
# - Plugin storage: inherent isolation via owner = plugin identity (set by SDK runtime)
# - Workspace storage: requires ctx.resources.storage.workspace_storage for AgentRunner
# - Workspace storage: requires ctx.resources.storage.workspace_storage for Runner
@self.action(RuntimeToLangBotAction.SET_BINARY_STORAGE)
async def set_binary_storage(data: dict[str, Any]) -> handler.ActionResponse:
@@ -2329,10 +2329,10 @@ class RuntimeConnectionHandler(handler.Handler):
async def retrieve_knowledge(data: dict[str, Any]) -> handler.ActionResponse:
"""Retrieve documents from any knowledge base.
For AgentRunner calls: requires run_id and validates kb_id against session.resources.knowledge_bases.
For Runner calls: requires run_id and validates kb_id against session.resources.knowledge_bases.
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
Note: SDK AgentRunAPIProxy.retrieve_knowledge calls this action with run_id.
Note: SDK RunnerAPIProxy.retrieve_knowledge calls this action with run_id.
"""
action_context, _ = await self._require_plugin_action_context()
execution_context = self._execution_context(action_context)
@@ -2340,10 +2340,10 @@ class RuntimeConnectionHandler(handler.Handler):
query_text = data['query_text']
top_k = data.get('top_k', 5)
filters = data.get('filters') or {}
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'knowledge_base', kb_id, self.ap, caller_plugin_identity, operation='retrieve'
@@ -2410,11 +2410,11 @@ class RuntimeConnectionHandler(handler.Handler):
async def retrieve_knowledge_base(data: dict[str, Any]) -> handler.ActionResponse:
"""Retrieve documents from a knowledge base within the current run or query scope.
For AgentRunner calls: requires run_id and validates kb_id against session.resources.knowledge_bases.
For Runner calls: requires run_id and validates kb_id against session.resources.knowledge_bases.
For regular plugin calls: no run_id, validates against pipeline's configured knowledge bases.
Note: This action has dual validation paths:
- AgentRunner: uses session_registry for permission check
- Runner: uses session_registry for permission check
- Regular plugin: uses RunnerConfigResolver.resolve_runner_config for pipeline-level check
"""
action_context, _ = await self._require_plugin_action_context()
@@ -2424,12 +2424,12 @@ class RuntimeConnectionHandler(handler.Handler):
query_text = data['query_text']
top_k = data.get('top_k', 5)
filters = data.get('filters') or {}
run_id = data.get('run_id') # Optional: present for AgentRunner calls
run_id = data.get('run_id') # Optional: present for Runner calls
caller_plugin_identity = data.get('caller_plugin_identity') # Optional: for cross-plugin validation
session = None
query = None
# Permission validation for AgentRunner calls
# Permission validation for Runner calls
if run_id:
session, error = await _validate_run_authorization(
run_id, 'knowledge_base', kb_id, self.ap, caller_plugin_identity, operation='retrieve'
@@ -2535,7 +2535,7 @@ class RuntimeConnectionHandler(handler.Handler):
)
agent_pull_actions.register(self)
agent_runner_actions.register(self)
runner_actions.register(self)
agent_state_actions.register(self)
@self.action(CommonAction.PING)
@@ -2834,7 +2834,7 @@ class RuntimeConnectionHandler(handler.Handler):
return result['tools']
async def list_agent_runners(self, include_plugins: list[str] | None = None) -> list[dict[str, Any]]:
async def list_runners(self, include_plugins: list[str] | None = None) -> list[dict[str, Any]]:
"""List agent runners from plugin runtime.
Returns list of dicts with:
@@ -2844,7 +2844,7 @@ class RuntimeConnectionHandler(handler.Handler):
- manifest
"""
result = await self.call_action(
LangBotToRuntimeAction.LIST_AGENT_RUNNERS,
LangBotToRuntimeAction.LIST_RUNNERS,
{
'include_plugins': include_plugins,
},
@@ -2853,20 +2853,20 @@ class RuntimeConnectionHandler(handler.Handler):
return result['runners']
async def run_agent(
async def run_runner(
self,
plugin_author: str,
plugin_name: str,
runner_name: str,
context: dict[str, Any],
) -> typing.AsyncGenerator[dict[str, Any], None]:
"""Run an AgentRunner component.
"""Run an Runner component.
Yields AgentRunResult dicts.
Yields RunnerResult dicts.
"""
timeout = self._get_runner_action_timeout(context)
gen = self.call_action_generator(
LangBotToRuntimeAction.RUN_AGENT,
LangBotToRuntimeAction.RUN_RUNNER,
{
'plugin_author': plugin_author,
'plugin_name': plugin_name,
@@ -16,7 +16,7 @@ from .agent_run_support import (
AGENT_RUN_ADMIN_PERMISSION,
RUNTIME_ADMIN_PERMISSION,
_plugin_runtime_action,
_has_agent_runner_admin_permission,
_has_runner_admin_permission,
_deadline_seconds_from_payload,
_get_run_authorization,
_authorize_target_run,
@@ -27,7 +27,7 @@ from .agent_run_support import (
_run_scope_filters,
_run_ledger_scope_filters,
_project_runner_descriptor_for_api,
_record_agent_runner_admin_action,
_record_runner_admin_action,
)
@@ -38,7 +38,7 @@ def register(h):
run_id = data.get('run_id')
target_run_id = data.get('target_run_id') or run_id
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -74,7 +74,7 @@ def register(h):
if auth_error:
return auth_error
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_get',
@@ -96,7 +96,7 @@ def register(h):
before_cursor = data.get('before_cursor')
limit = data.get('limit', 50)
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -159,7 +159,7 @@ def register(h):
**scope_filters,
)
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_list',
@@ -185,10 +185,10 @@ def register(h):
@h.action(_plugin_runtime_action('RUNNER_LIST', 'runner_list'))
async def runner_list(data: dict[str, Any]) -> handler.ActionResponse:
"""List Host-discovered AgentRunner descriptors."""
"""List Host-discovered Runner descriptors."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -213,7 +213,7 @@ def register(h):
if include_plugins is not None and not isinstance(include_plugins, list):
return handler.ActionResponse.error(message='include_plugins must be a list')
registry = getattr(h.ap, 'agent_runner_registry', None)
registry = getattr(h.ap, 'runner_registry', None)
if registry is None:
return handler.ActionResponse.success(data={'items': []})
@@ -231,7 +231,7 @@ def register(h):
)
items = [_project_runner_descriptor_for_api(item) for item in runners]
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
None,
action='runner_list',
@@ -257,7 +257,7 @@ def register(h):
limit = data.get('limit', 50)
direction = data.get('direction', 'forward')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -307,7 +307,7 @@ def register(h):
direction=str(direction or 'forward'),
)
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_events_page',
@@ -333,7 +333,7 @@ def register(h):
run_id = data.get('run_id')
target_run_id = data.get('target_run_id') or run_id
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -376,7 +376,7 @@ def register(h):
if not updated:
return handler.ActionResponse.error(message=f'Run {target_run_id} not found')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_cancel',
@@ -397,7 +397,7 @@ def register(h):
target_run_id = data.get('target_run_id') or run_id
caller_plugin_identity = data.get('caller_plugin_identity')
result = data.get('result') if isinstance(data.get('result'), dict) else {}
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -479,7 +479,7 @@ def register(h):
metadata=metadata,
)
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_append_result',
@@ -500,7 +500,7 @@ def register(h):
target_run_id = data.get('target_run_id') or run_id
caller_plugin_identity = data.get('caller_plugin_identity')
status = data.get('status')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -558,7 +558,7 @@ def register(h):
if not updated:
return handler.ActionResponse.error(message=f'Run {target_run_id} not found')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_finalize',
@@ -578,7 +578,7 @@ def register(h):
run_id = data.get('run_id')
runtime_id = data.get('runtime_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -617,7 +617,7 @@ def register(h):
heartbeat_deadline_seconds=_deadline_seconds_from_payload(data),
)
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runtime_register',
@@ -637,7 +637,7 @@ def register(h):
run_id = data.get('run_id')
runtime_id = data.get('runtime_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -675,7 +675,7 @@ def register(h):
if runtime is None:
return handler.ActionResponse.error(message=f'Runtime {runtime_id} not found')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runtime_heartbeat',
@@ -694,7 +694,7 @@ def register(h):
"""List Host-owned runtime registry records."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -730,7 +730,7 @@ def register(h):
limit=data.get('limit', 50),
)
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runtime_list',
@@ -759,7 +759,7 @@ def register(h):
"""Reconcile stale runtime heartbeats and expired claim leases."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -796,7 +796,7 @@ def register(h):
)
released_claims = await store.release_expired_claims()
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runtime_reconcile',
@@ -824,7 +824,7 @@ def register(h):
"""Get run statistics within a time window (admin-only)."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -858,7 +858,7 @@ def register(h):
end_time=end_time,
runner_id=runner_id,
)
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_stats',
@@ -880,7 +880,7 @@ def register(h):
"""Get runtime registry statistics (admin-only)."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -906,7 +906,7 @@ def register(h):
try:
stats = await store.get_runtime_stats()
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runtime_stats',
@@ -924,7 +924,7 @@ def register(h):
"""Get runner-aggregated statistics (admin-only)."""
run_id = data.get('run_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
AGENT_RUN_ADMIN_PERMISSION,
@@ -958,7 +958,7 @@ def register(h):
end_time=end_time,
limit=limit,
)
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='runner_stats',
@@ -981,7 +981,7 @@ def register(h):
run_id = data.get('run_id')
runtime_id = data.get('runtime_id')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -1035,7 +1035,7 @@ def register(h):
if run is None:
return handler.ActionResponse.error(message='No queued run available')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_claim',
@@ -1061,7 +1061,7 @@ def register(h):
runtime_id = data.get('runtime_id')
claim_token = data.get('claim_token')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -1108,7 +1108,7 @@ def register(h):
if run is None:
return handler.ActionResponse.error(message=f'Run claim {target_run_id} not found')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_renew_claim',
@@ -1131,7 +1131,7 @@ def register(h):
runtime_id = data.get('runtime_id')
claim_token = data.get('claim_token')
caller_plugin_identity = data.get('caller_plugin_identity')
is_admin = _has_agent_runner_admin_permission(
is_admin = _has_runner_admin_permission(
h.ap,
caller_plugin_identity,
RUNTIME_ADMIN_PERMISSION,
@@ -1184,7 +1184,7 @@ def register(h):
if run is None:
return handler.ActionResponse.error(message=f'Run claim {target_run_id} not found')
if is_admin:
await _record_agent_runner_admin_action(
await _record_runner_admin_action(
h.ap,
store,
action='run_release_claim',