test(agent-runner): strengthen local agent e2e gate

This commit is contained in:
huanghuoguoguo
2026-07-01 20:20:43 +08:00
parent d0f8f080e9
commit 995888f6b2
44 changed files with 5678 additions and 1040 deletions
@@ -73,8 +73,13 @@ class PipelinesRouterGroup(group.RouterGroup):
plugins = await self.ap.plugin_connector.list_plugins(component_kinds=pipeline_component_kinds)
mcp_servers = await self.ap.mcp_service.get_mcp_servers(contain_runtime_info=True)
# Get available skills
available_skills = await self.ap.skill_service.list_skills()
# Skill listing depends on Box. Pipeline plugin/MCP binding
# must remain usable when Box is slow or unavailable.
try:
available_skills = await self.ap.skill_service.list_skills()
except Exception as exc:
self.ap.logger.warning('Unable to list skills for pipeline extensions: %s', exc)
available_skills = []
extensions_prefs = pipeline.get('extensions_preferences', {})
return self.success(
+12 -3
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import io
import inspect
import logging
import os
import posixpath
import zipfile
@@ -9,6 +10,8 @@ from typing import Optional
from urllib.parse import quote, unquote, urlparse
import httpx
from langbot_plugin.box.errors import BoxError
from langbot_plugin.entities.io.errors import ActionCallError, ActionCallTimeoutError
from ....core import app
from ....skill.utils import parse_frontmatter
@@ -33,6 +36,8 @@ _GITHUB_ASSET_HOSTS = {
'codeload.github.com',
}
logger = logging.getLogger(__name__)
class SkillService:
"""Filesystem-backed skill management service."""
@@ -81,12 +86,16 @@ class SkillService:
async def list_skills(self) -> list[dict]:
# When Box is unavailable, surface an empty list rather than raising —
# the skills page should render cleanly, and the UI separately renders
# a "Box disabled / unavailable" banner via useBoxStatus.
# the skills page and unrelated extension surfaces should render
# cleanly, and the UI separately renders Box status via useBoxStatus.
box_service = self._box_service()
if box_service is None:
return []
return [self._serialize_skill(skill) for skill in await box_service.list_skills()]
try:
return [self._serialize_skill(skill) for skill in await box_service.list_skills()]
except (ActionCallTimeoutError, ActionCallError, BoxError, TimeoutError, ConnectionError) as exc:
logger.warning('Box skill list unavailable; returning an empty skill list: %s', exc)
return []
async def get_skill(self, skill_name: str) -> Optional[dict]:
box_service = self._box_service()