mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-28 13:17:14 +00:00
fix(web): make processor debugging reliable
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
"""Agent runner errors."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
class AgentRunnerError(Exception):
|
||||
"""Base error for agent runner operations."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class RunnerNotFoundError(AgentRunnerError):
|
||||
"""Runner not found in registry."""
|
||||
|
||||
def __init__(self, runner_id: str):
|
||||
self.runner_id = runner_id
|
||||
super().__init__(f'Agent runner not found: {runner_id}')
|
||||
@@ -16,6 +19,7 @@ class RunnerNotFoundError(AgentRunnerError):
|
||||
|
||||
class RunnerNotAuthorizedError(AgentRunnerError):
|
||||
"""Runner not authorized for this binding."""
|
||||
|
||||
def __init__(self, runner_id: str, bound_plugins: list[str] | None):
|
||||
self.runner_id = runner_id
|
||||
self.bound_plugins = bound_plugins
|
||||
@@ -24,6 +28,7 @@ class RunnerNotAuthorizedError(AgentRunnerError):
|
||||
|
||||
class RunnerProtocolError(AgentRunnerError):
|
||||
"""Runner protocol version mismatch or invalid manifest."""
|
||||
|
||||
def __init__(self, runner_id: str, message: str):
|
||||
self.runner_id = runner_id
|
||||
super().__init__(f'Agent runner protocol error for {runner_id}: {message}')
|
||||
@@ -31,7 +36,16 @@ class RunnerProtocolError(AgentRunnerError):
|
||||
|
||||
class RunnerExecutionError(AgentRunnerError):
|
||||
"""Runner execution failed."""
|
||||
def __init__(self, runner_id: str, message: str, retryable: bool = False):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
runner_id: str,
|
||||
message: str,
|
||||
retryable: bool = False,
|
||||
error_code: str | None = None,
|
||||
):
|
||||
self.runner_id = runner_id
|
||||
self.message = message
|
||||
self.retryable = retryable
|
||||
self.error_code = error_code
|
||||
super().__init__(f'Agent runner {runner_id} execution failed: {message}')
|
||||
|
||||
@@ -58,21 +58,21 @@ class AgentRunnerInvoker:
|
||||
except asyncio.TimeoutError as e:
|
||||
raise RunnerExecutionError(
|
||||
descriptor.id,
|
||||
'Runner timed out (code: runner.timeout)',
|
||||
'Runner timed out',
|
||||
retryable=True,
|
||||
error_code='runner.timeout',
|
||||
) from e
|
||||
except ActionCallTimeoutError as e:
|
||||
raise RunnerExecutionError(
|
||||
descriptor.id,
|
||||
f'{e} (code: runner.timeout)',
|
||||
str(e),
|
||||
retryable=True,
|
||||
error_code='runner.timeout',
|
||||
) from e
|
||||
except RunnerExecutionError:
|
||||
raise
|
||||
except Exception as e:
|
||||
self.ap.logger.error(
|
||||
f'Runner {descriptor.id} unexpected error: {traceback.format_exc()}'
|
||||
)
|
||||
self.ap.logger.error(f'Runner {descriptor.id} unexpected error: {traceback.format_exc()}')
|
||||
raise RunnerExecutionError(
|
||||
descriptor.id,
|
||||
str(e),
|
||||
|
||||
@@ -152,10 +152,14 @@ class AgentResultNormalizer:
|
||||
error_msg = data.get('error', 'Unknown error')
|
||||
error_code = data.get('code', 'unknown')
|
||||
retryable = data.get('retryable', False)
|
||||
normalized_error_code = str(error_code or '').strip()
|
||||
raise RunnerExecutionError(
|
||||
descriptor.id,
|
||||
f'{error_msg} (code: {error_code})',
|
||||
str(error_msg),
|
||||
retryable=retryable,
|
||||
error_code=(
|
||||
normalized_error_code if normalized_error_code and normalized_error_code != 'unknown' else None
|
||||
),
|
||||
)
|
||||
|
||||
elif result_type == 'action.requested':
|
||||
|
||||
@@ -2,6 +2,13 @@ from __future__ import annotations
|
||||
|
||||
import quart
|
||||
|
||||
from .....agent.runner.errors import (
|
||||
AgentRunnerError,
|
||||
RunnerExecutionError,
|
||||
RunnerNotAuthorizedError,
|
||||
RunnerNotFoundError,
|
||||
RunnerProtocolError,
|
||||
)
|
||||
from ...authz import Permission, require_permission
|
||||
from ...context import RequestContext
|
||||
from .. import group
|
||||
@@ -63,6 +70,36 @@ class AgentsRouterGroup(group.RouterGroup):
|
||||
)
|
||||
except ValueError as exc:
|
||||
return self.http_status(400, -1, str(exc))
|
||||
except RunnerExecutionError as exc:
|
||||
return self.http_status(
|
||||
422,
|
||||
exc.error_code or 'runner_execution_failed',
|
||||
exc.message,
|
||||
)
|
||||
except RunnerNotFoundError:
|
||||
return self.http_status(
|
||||
409,
|
||||
'runner_not_found',
|
||||
'The configured Agent runner is unavailable',
|
||||
)
|
||||
except RunnerNotAuthorizedError:
|
||||
return self.http_status(
|
||||
403,
|
||||
'runner_not_authorized',
|
||||
'The configured Agent runner is not authorized',
|
||||
)
|
||||
except RunnerProtocolError:
|
||||
return self.http_status(
|
||||
502,
|
||||
'runner_protocol_error',
|
||||
'The Agent runner returned an invalid response',
|
||||
)
|
||||
except AgentRunnerError:
|
||||
return self.http_status(
|
||||
502,
|
||||
'runner_error',
|
||||
'The Agent runner could not complete this test',
|
||||
)
|
||||
return self.success(data=result)
|
||||
|
||||
@self.route(
|
||||
|
||||
@@ -25,7 +25,7 @@ class BanWordFilter(filter_model.ContentFilter):
|
||||
return entities.FilterResult(
|
||||
level=entities.ResultLevel.BLOCK,
|
||||
replacement='',
|
||||
user_notice='内容检查规则执行失败,请联系管理员',
|
||||
user_notice='内容安全检查配置有误,请检查敏感词设置',
|
||||
console_notice=f'Sensitive-word regex rejected: {exc}',
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ from collections.abc import Sequence
|
||||
import regex
|
||||
|
||||
|
||||
MAX_PATTERN_COUNT = 64
|
||||
# The bundled sensitive-word list already contains more than 64 entries. Keep
|
||||
# the deterministic cap, but leave enough room for the built-in defaults and
|
||||
# reasonable administrator customisation.
|
||||
MAX_PATTERN_COUNT = 256
|
||||
MAX_PATTERN_CHARS = 1024
|
||||
MAX_INPUT_CHARS = 1024 * 1024
|
||||
MAX_REPLACEMENT_CHARS = 64
|
||||
|
||||
Reference in New Issue
Block a user