mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-16 14:57:15 +00:00
fix(runner): align SDK pin and complete real runtime verification (#2525)
* fix(runner): align SDK pin and workspace-aware integration fixtures * fix(ci): format sources and resolve current migration head * test(persistence): align standalone migration fixtures with current models * test(web): align smoke fixtures with current processor UI --------- Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
@@ -17,6 +17,7 @@ from quart import Quart, request, Response, jsonify
|
||||
|
||||
from langbot.libs.wecom_ai_bot_api import wecombotevent
|
||||
from langbot.libs.wecom_ai_bot_api.WXBizMsgCrypt3 import WXBizMsgCrypt
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langbot.pkg.platform.logger import EventLogger
|
||||
from langbot.pkg.utils import httpclient
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""EventLog store for writing and querying event records."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
@@ -44,9 +45,7 @@ class EventLogStore:
|
||||
|
||||
def __init__(self, engine: AsyncEngine):
|
||||
self.engine = engine
|
||||
self._session_factory = sessionmaker(
|
||||
engine, class_=AsyncSession, expire_on_commit=False
|
||||
)
|
||||
self._session_factory = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
async def append_event(
|
||||
self,
|
||||
@@ -101,7 +100,7 @@ class EventLogStore:
|
||||
|
||||
# Truncate input summary if too long
|
||||
if input_summary and len(input_summary) > self.MAX_INPUT_SUMMARY_LENGTH:
|
||||
input_summary = input_summary[:self.MAX_INPUT_SUMMARY_LENGTH - 3] + "..."
|
||||
input_summary = input_summary[: self.MAX_INPUT_SUMMARY_LENGTH - 3] + '...'
|
||||
|
||||
async with self._session_factory() as session:
|
||||
event = EventLog(
|
||||
@@ -144,9 +143,7 @@ class EventLogStore:
|
||||
Event record as dict, or None if not found
|
||||
"""
|
||||
async with self._session_factory() as session:
|
||||
result = await session.execute(
|
||||
sqlalchemy.select(EventLog).where(EventLog.event_id == event_id)
|
||||
)
|
||||
result = await session.execute(sqlalchemy.select(EventLog).where(EventLog.event_id == event_id))
|
||||
row = result.scalars().first()
|
||||
if row is None:
|
||||
return None
|
||||
@@ -282,9 +279,7 @@ class EventLogStore:
|
||||
) -> int:
|
||||
"""Delete EventLog rows created before the supplied timestamp."""
|
||||
async with self._session_factory() as session:
|
||||
result = await session.execute(
|
||||
sqlalchemy.delete(EventLog).where(EventLog.created_at < before)
|
||||
)
|
||||
result = await session.execute(sqlalchemy.delete(EventLog).where(EventLog.created_at < before))
|
||||
await session.commit()
|
||||
return result.rowcount or 0
|
||||
|
||||
|
||||
@@ -71,17 +71,8 @@ class EmbedRouterGroup(group.RouterGroup):
|
||||
``web_page_bot``, is disabled, or has no Pipeline target for messages.
|
||||
"""
|
||||
bot = await self.ap.platform_mgr.resolve_public_bot(bot_uuid)
|
||||
pipeline_uuid = (
|
||||
bot.get_pipeline_target_for_event_type('message.received')
|
||||
if bot is not None
|
||||
else None
|
||||
)
|
||||
if (
|
||||
bot is not None
|
||||
and bot.bot_entity.adapter == 'web_page_bot'
|
||||
and bot.bot_entity.enable
|
||||
and pipeline_uuid
|
||||
):
|
||||
pipeline_uuid = bot.get_pipeline_target_for_event_type('message.received') if bot is not None else None
|
||||
if bot is not None and bot.bot_entity.adapter == 'web_page_bot' and bot.bot_entity.enable and pipeline_uuid:
|
||||
return bot, pipeline_uuid
|
||||
return None, None
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@ class ToolsRouterGroup(group.RouterGroup):
|
||||
self,
|
||||
request_context: RequestContext,
|
||||
) -> list[dict] | None:
|
||||
pipeline_uuid = quart.request.args.get(
|
||||
'pipeline_uuid'
|
||||
) or quart.request.args.get('pipeline_id')
|
||||
pipeline_uuid = quart.request.args.get('pipeline_uuid') or quart.request.args.get('pipeline_id')
|
||||
bound_plugins: list[str] | None = None
|
||||
bound_mcp_servers: list[str] | None = None
|
||||
|
||||
@@ -28,14 +26,9 @@ class ToolsRouterGroup(group.RouterGroup):
|
||||
if pipeline is None:
|
||||
return None
|
||||
|
||||
extensions_prefs = normalize_extension_preferences(
|
||||
pipeline.get('extensions_preferences')
|
||||
)
|
||||
extensions_prefs = normalize_extension_preferences(pipeline.get('extensions_preferences'))
|
||||
if not extensions_prefs['enable_all_plugins']:
|
||||
bound_plugins = [
|
||||
f'{plugin["author"]}/{plugin["name"]}'
|
||||
for plugin in extensions_prefs['plugins']
|
||||
]
|
||||
bound_plugins = [f'{plugin["author"]}/{plugin["name"]}' for plugin in extensions_prefs['plugins']]
|
||||
if not extensions_prefs['enable_all_mcp_servers']:
|
||||
bound_mcp_servers = extensions_prefs['mcp_servers']
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Transcript persistence entity for conversation history projection."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
@@ -48,12 +48,16 @@ def upgrade() -> None:
|
||||
sa.column('source', sa.String(32)),
|
||||
sa.column('created_by_account_uuid', sa.String(36)),
|
||||
)
|
||||
workspace_uuids = conn.execute(
|
||||
sa.select(workspaces.c.uuid).where(
|
||||
workspaces.c.instance_uuid == instance_uuid.strip(),
|
||||
workspaces.c.source == 'local',
|
||||
workspace_uuids = (
|
||||
conn.execute(
|
||||
sa.select(workspaces.c.uuid).where(
|
||||
workspaces.c.instance_uuid == instance_uuid.strip(),
|
||||
workspaces.c.source == 'local',
|
||||
)
|
||||
)
|
||||
).scalars().all()
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
if not workspace_uuids:
|
||||
return
|
||||
if len(workspace_uuids) > 1:
|
||||
@@ -99,10 +103,7 @@ def upgrade() -> None:
|
||||
sa.column('status', sa.String(32)),
|
||||
)
|
||||
owner_account_uuid = conn.execute(
|
||||
sa.select(users.c.uuid)
|
||||
.where(users.c.status == 'active')
|
||||
.order_by(users.c.id)
|
||||
.limit(1)
|
||||
sa.select(users.c.uuid).where(users.c.status == 'active').order_by(users.c.id).limit(1)
|
||||
).scalar_one_or_none()
|
||||
if owner_account_uuid is None:
|
||||
return
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ Revision ID: 58846a8d7a81
|
||||
Revises: 0005_add_llm_context_length
|
||||
Create Date: 2026-05-23 15:41:47.030841
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ Revision ID: 7b2c1d9e4f30
|
||||
Revises: 6dfd3dd7f0c7
|
||||
Create Date: 2026-06-12
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
@@ -90,9 +90,7 @@ def upgrade() -> None:
|
||||
)
|
||||
else:
|
||||
_add_column_if_missing('agent_run', sa.Column('queue_name', sa.String(255), nullable=True))
|
||||
_add_column_if_missing(
|
||||
'agent_run', sa.Column('priority', sa.Integer(), nullable=False, server_default='0')
|
||||
)
|
||||
_add_column_if_missing('agent_run', sa.Column('priority', sa.Integer(), nullable=False, server_default='0'))
|
||||
_add_column_if_missing('agent_run', sa.Column('requested_runtime_id', sa.String(255), nullable=True))
|
||||
_add_column_if_missing('agent_run', sa.Column('claimed_by_runtime_id', sa.String(255), nullable=True))
|
||||
_add_column_if_missing('agent_run', sa.Column('claim_token', sa.String(255), nullable=True))
|
||||
|
||||
@@ -50,22 +50,16 @@ def normalize_extension_preferences(value: typing.Any) -> dict[str, typing.Any]:
|
||||
normalized['enable_all_plugins'] = value.get('enable_all_plugins', True) is True
|
||||
normalized['enable_all_mcp_servers'] = value.get('enable_all_mcp_servers', True) is True
|
||||
normalized['enable_all_skills'] = value.get('enable_all_skills', True) is True
|
||||
normalized['mcp_resource_agent_read_enabled'] = (
|
||||
value.get('mcp_resource_agent_read_enabled', True) is True
|
||||
)
|
||||
normalized['mcp_resource_agent_read_enabled'] = value.get('mcp_resource_agent_read_enabled', True) is True
|
||||
|
||||
plugins = value.get('plugins', [])
|
||||
plugins_are_valid = isinstance(plugins, list) and all(
|
||||
_valid_plugin_binding(plugin) for plugin in plugins
|
||||
)
|
||||
plugins_are_valid = isinstance(plugins, list) and all(_valid_plugin_binding(plugin) for plugin in plugins)
|
||||
normalized['plugins'] = list(plugins) if plugins_are_valid else []
|
||||
if not plugins_are_valid:
|
||||
normalized['enable_all_plugins'] = False
|
||||
|
||||
mcp_servers = value.get('mcp_servers', [])
|
||||
mcp_servers_are_valid = isinstance(mcp_servers, list) and all(
|
||||
_valid_name(server) for server in mcp_servers
|
||||
)
|
||||
mcp_servers_are_valid = isinstance(mcp_servers, list) and all(_valid_name(server) for server in mcp_servers)
|
||||
normalized['mcp_servers'] = list(mcp_servers) if mcp_servers_are_valid else []
|
||||
if not mcp_servers_are_valid:
|
||||
normalized['enable_all_mcp_servers'] = False
|
||||
@@ -151,6 +145,4 @@ def _validate_list_field(
|
||||
raise ValueError(f"{context} field '{field_label}' must be a list")
|
||||
for index, item in enumerate(items):
|
||||
if not item_validator(item):
|
||||
raise ValueError(
|
||||
f"{context} field '{field_label}[{index}]' must be {item_description}"
|
||||
)
|
||||
raise ValueError(f"{context} field '{field_label}[{index}]' must be {item_description}")
|
||||
|
||||
@@ -65,8 +65,12 @@ class OfficialAccountMessageConverter(abstract_platform_adapter.AbstractMessageC
|
||||
else:
|
||||
components.append(platform_message.Unknown(text='[officialaccount voice message without media id]'))
|
||||
elif event.type == 'event':
|
||||
components.append(platform_message.Unknown(text=f'[officialaccount event: {event.detail_type or "unknown"}]'))
|
||||
components.append(
|
||||
platform_message.Unknown(text=f'[officialaccount event: {event.detail_type or "unknown"}]')
|
||||
)
|
||||
else:
|
||||
components.append(platform_message.Unknown(text=f'[unsupported officialaccount msgtype: {event.type or "unknown"}]'))
|
||||
components.append(
|
||||
platform_message.Unknown(text=f'[unsupported officialaccount msgtype: {event.type or "unknown"}]')
|
||||
)
|
||||
|
||||
return platform_message.MessageChain(components)
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
from langbot.pkg.platform.adapters.qqofficial.adapter import QQOfficialAdapter
|
||||
|
||||
__all__ = ['QQOfficialAdapter']
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ class QQOfficialAPIMixin:
|
||||
self,
|
||||
group_id: typing.Union[int, str],
|
||||
) -> list[platform_entities.UserGroupMember]:
|
||||
return [member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)]
|
||||
return [
|
||||
member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)
|
||||
]
|
||||
|
||||
async def edit_message(
|
||||
self,
|
||||
@@ -100,4 +102,3 @@ class QQOfficialAPIMixin:
|
||||
|
||||
async def leave_group(self, group_id: typing.Union[int, str]):
|
||||
raise NotSupportedError('leave_group')
|
||||
|
||||
|
||||
@@ -8,4 +8,3 @@ except ModuleNotFoundError:
|
||||
def __init__(self, api_name: str, *args):
|
||||
super().__init__(f"API '{api_name}' is not supported by this adapter", *args)
|
||||
self.api_name = api_name
|
||||
|
||||
|
||||
@@ -34,4 +34,3 @@ PLATFORM_API_MAP: dict[str, typing.Callable[[typing.Any, dict], typing.Awaitable
|
||||
'get_gateway_url': get_gateway_url,
|
||||
'get_mode': get_mode,
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,9 @@ class SlackAPIMixin:
|
||||
self,
|
||||
group_id: typing.Union[int, str],
|
||||
) -> list[platform_entities.UserGroupMember]:
|
||||
return [member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)]
|
||||
return [
|
||||
member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)
|
||||
]
|
||||
|
||||
async def get_group_member_info(
|
||||
self,
|
||||
|
||||
@@ -19,7 +19,9 @@ class SlackEventConverter(abstract_platform_adapter.AbstractEventConverter):
|
||||
async def yiri2target(event: platform_events.Event) -> typing.Any:
|
||||
return getattr(event, 'source_platform_object', None)
|
||||
|
||||
async def target2legacy(self, event: SlackEvent) -> platform_events.FriendMessage | platform_events.GroupMessage | None:
|
||||
async def target2legacy(
|
||||
self, event: SlackEvent
|
||||
) -> platform_events.FriendMessage | platform_events.GroupMessage | None:
|
||||
eba_event = await self.target2yiri(event)
|
||||
if not isinstance(eba_event, platform_events.MessageReceivedEvent):
|
||||
return None
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from langbot.pkg.platform.adapters.telegram.adapter import TelegramAdapter
|
||||
|
||||
__all__ = ["TelegramAdapter"]
|
||||
__all__ = ['TelegramAdapter']
|
||||
|
||||
@@ -14,7 +14,7 @@ async def pin_message(bot: telegram.Bot, params: dict) -> dict:
|
||||
message_id=params['message_id'],
|
||||
disable_notification=params.get('disable_notification', False),
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def unpin_message(bot: telegram.Bot, params: dict) -> dict:
|
||||
@@ -23,26 +23,26 @@ async def unpin_message(bot: telegram.Bot, params: dict) -> dict:
|
||||
chat_id=params['chat_id'],
|
||||
message_id=params.get('message_id'),
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def unpin_all_messages(bot: telegram.Bot, params: dict) -> dict:
|
||||
"""Unpin all messages in a chat."""
|
||||
await bot.unpin_all_chat_messages(chat_id=params['chat_id'])
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def get_chat_administrators(bot: telegram.Bot, params: dict) -> dict:
|
||||
"""Get chat administrator list."""
|
||||
admins = await bot.get_chat_administrators(chat_id=params['chat_id'])
|
||||
return {
|
||||
"administrators": [
|
||||
'administrators': [
|
||||
{
|
||||
"user_id": a.user.id,
|
||||
"username": a.user.username,
|
||||
"first_name": a.user.first_name,
|
||||
"status": a.status,
|
||||
"custom_title": getattr(a, 'custom_title', None),
|
||||
'user_id': a.user.id,
|
||||
'username': a.user.username,
|
||||
'first_name': a.user.first_name,
|
||||
'status': a.status,
|
||||
'custom_title': getattr(a, 'custom_title', None),
|
||||
}
|
||||
for a in admins
|
||||
]
|
||||
@@ -55,7 +55,7 @@ async def set_chat_title(bot: telegram.Bot, params: dict) -> dict:
|
||||
chat_id=params['chat_id'],
|
||||
title=params['title'],
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def set_chat_description(bot: telegram.Bot, params: dict) -> dict:
|
||||
@@ -64,13 +64,13 @@ async def set_chat_description(bot: telegram.Bot, params: dict) -> dict:
|
||||
chat_id=params['chat_id'],
|
||||
description=params.get('description', ''),
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def get_chat_member_count(bot: telegram.Bot, params: dict) -> dict:
|
||||
"""Get chat member count."""
|
||||
count = await bot.get_chat_member_count(chat_id=params['chat_id'])
|
||||
return {"count": count}
|
||||
return {'count': count}
|
||||
|
||||
|
||||
async def send_chat_action(bot: telegram.Bot, params: dict) -> dict:
|
||||
@@ -79,7 +79,7 @@ async def send_chat_action(bot: telegram.Bot, params: dict) -> dict:
|
||||
chat_id=params['chat_id'],
|
||||
action=params.get('action', 'typing'),
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
async def create_chat_invite_link(bot: telegram.Bot, params: dict) -> dict:
|
||||
@@ -91,10 +91,10 @@ async def create_chat_invite_link(bot: telegram.Bot, params: dict) -> dict:
|
||||
member_limit=params.get('member_limit'),
|
||||
)
|
||||
return {
|
||||
"invite_link": link.invite_link,
|
||||
"name": link.name,
|
||||
"is_primary": link.is_primary,
|
||||
"is_revoked": link.is_revoked,
|
||||
'invite_link': link.invite_link,
|
||||
'name': link.name,
|
||||
'is_primary': link.is_primary,
|
||||
'is_revoked': link.is_revoked,
|
||||
}
|
||||
|
||||
|
||||
@@ -106,20 +106,20 @@ async def answer_callback_query(bot: telegram.Bot, params: dict) -> dict:
|
||||
show_alert=params.get('show_alert', False),
|
||||
url=params.get('url'),
|
||||
)
|
||||
return {"ok": True}
|
||||
return {'ok': True}
|
||||
|
||||
|
||||
# ---- Action dispatch table ----
|
||||
|
||||
PLATFORM_API_MAP: dict[str, typing.Callable[[telegram.Bot, dict], typing.Awaitable[dict]]] = {
|
||||
"pin_message": pin_message,
|
||||
"unpin_message": unpin_message,
|
||||
"unpin_all_messages": unpin_all_messages,
|
||||
"get_chat_administrators": get_chat_administrators,
|
||||
"set_chat_title": set_chat_title,
|
||||
"set_chat_description": set_chat_description,
|
||||
"get_chat_member_count": get_chat_member_count,
|
||||
"send_chat_action": send_chat_action,
|
||||
"create_chat_invite_link": create_chat_invite_link,
|
||||
"answer_callback_query": answer_callback_query,
|
||||
'pin_message': pin_message,
|
||||
'unpin_message': unpin_message,
|
||||
'unpin_all_messages': unpin_all_messages,
|
||||
'get_chat_administrators': get_chat_administrators,
|
||||
'set_chat_title': set_chat_title,
|
||||
'set_chat_description': set_chat_description,
|
||||
'get_chat_member_count': get_chat_member_count,
|
||||
'send_chat_action': send_chat_action,
|
||||
'create_chat_invite_link': create_chat_invite_link,
|
||||
'answer_callback_query': answer_callback_query,
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ from enum import Enum
|
||||
|
||||
class TelegramChatType(str, Enum):
|
||||
"""Telegram chat type."""
|
||||
PRIVATE = "private"
|
||||
GROUP = "group"
|
||||
SUPERGROUP = "supergroup"
|
||||
CHANNEL = "channel"
|
||||
|
||||
PRIVATE = 'private'
|
||||
GROUP = 'group'
|
||||
SUPERGROUP = 'supergroup'
|
||||
CHANNEL = 'channel'
|
||||
|
||||
@@ -54,7 +54,9 @@ class WecomBotAPIMixin:
|
||||
self,
|
||||
group_id: typing.Union[int, str],
|
||||
) -> list[platform_entities.UserGroupMember]:
|
||||
return [member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)]
|
||||
return [
|
||||
member for (cached_group_id, _), member in self._member_cache.items() if cached_group_id == str(group_id)
|
||||
]
|
||||
|
||||
async def upload_file(self, file_data: bytes, filename: str) -> str:
|
||||
raise NotSupportedError('upload_file')
|
||||
|
||||
@@ -19,7 +19,9 @@ class WecomBotEventConverter(abstract_platform_adapter.AbstractEventConverter):
|
||||
async def yiri2target(event: platform_events.Event) -> typing.Any:
|
||||
return getattr(event, 'source_platform_object', None)
|
||||
|
||||
async def target2legacy(self, event: WecomBotEvent) -> platform_events.FriendMessage | platform_events.GroupMessage | None:
|
||||
async def target2legacy(
|
||||
self, event: WecomBotEvent
|
||||
) -> platform_events.FriendMessage | platform_events.GroupMessage | None:
|
||||
eba_event = await self.target2yiri(event)
|
||||
if not isinstance(eba_event, platform_events.MessageReceivedEvent):
|
||||
return None
|
||||
@@ -50,7 +52,9 @@ class WecomBotEventConverter(abstract_platform_adapter.AbstractEventConverter):
|
||||
async def target2yiri(self, event: WecomBotEvent) -> platform_events.Event:
|
||||
if event.type in {'single', 'group'} and event.msgtype != 'event':
|
||||
return await self.message_to_eba(event)
|
||||
return self.platform_specific(event, f'wecombot.{event.get("eventtype") or event.msgtype or event.type or "unknown"}')
|
||||
return self.platform_specific(
|
||||
event, f'wecombot.{event.get("eventtype") or event.msgtype or event.type or "unknown"}'
|
||||
)
|
||||
|
||||
async def message_to_eba(self, event: WecomBotEvent) -> platform_events.MessageReceivedEvent:
|
||||
sender = platform_entities.User(id=event.userid, nickname=event.username or event.userid)
|
||||
|
||||
@@ -17,7 +17,9 @@ class WecomCSEventConverter(abstract_platform_adapter.AbstractEventConverter):
|
||||
return getattr(event, 'source_platform_object', None)
|
||||
|
||||
@staticmethod
|
||||
async def target2legacy(event: WecomCSEvent, bot: WecomCSClient | None = None) -> platform_events.FriendMessage | None:
|
||||
async def target2legacy(
|
||||
event: WecomCSEvent, bot: WecomCSClient | None = None
|
||||
) -> platform_events.FriendMessage | None:
|
||||
eba_event = await WecomCSEventConverter.target2yiri(event, bot)
|
||||
if hasattr(eba_event, 'to_legacy_event'):
|
||||
return eba_event.to_legacy_event()
|
||||
@@ -30,7 +32,9 @@ class WecomCSEventConverter(abstract_platform_adapter.AbstractEventConverter):
|
||||
return WecomCSEventConverter.platform_specific(event, f'wecomcs.{event.type or "unknown"}')
|
||||
|
||||
@staticmethod
|
||||
async def message_to_eba(event: WecomCSEvent, bot: WecomCSClient | None = None) -> platform_events.MessageReceivedEvent:
|
||||
async def message_to_eba(
|
||||
event: WecomCSEvent, bot: WecomCSClient | None = None
|
||||
) -> platform_events.MessageReceivedEvent:
|
||||
message_chain = await WecomCSMessageConverter.target2yiri(event)
|
||||
sender = await WecomCSEventConverter.user_from_event(event, bot)
|
||||
return platform_events.MessageReceivedEvent(
|
||||
|
||||
@@ -89,10 +89,12 @@ def format_human_input_text(
|
||||
if actions:
|
||||
lines.append('')
|
||||
if input_defs:
|
||||
lines.extend([
|
||||
'Reply with action plus field values to continue:',
|
||||
' action: <number or title>',
|
||||
])
|
||||
lines.extend(
|
||||
[
|
||||
'Reply with action plus field values to continue:',
|
||||
' action: <number or title>',
|
||||
]
|
||||
)
|
||||
else:
|
||||
lines.append('Reply with the number or title to continue:')
|
||||
for idx, action in enumerate(actions, start=1):
|
||||
|
||||
@@ -2327,15 +2327,9 @@ class MCPLoader(loader.ToolLoader):
|
||||
|
||||
return items
|
||||
|
||||
def _session_by_source_id(
|
||||
self, context: TenantContext, source_id: str
|
||||
) -> RuntimeMCPSession | None:
|
||||
def _session_by_source_id(self, context: TenantContext, source_id: str) -> RuntimeMCPSession | None:
|
||||
return next(
|
||||
(
|
||||
session
|
||||
for session in self._sessions_for_context(context)
|
||||
if session.server_uuid == source_id
|
||||
),
|
||||
(session for session in self._sessions_for_context(context) if session.server_uuid == source_id),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -2397,9 +2391,7 @@ class MCPLoader(loader.ToolLoader):
|
||||
source_id: str | None = None,
|
||||
) -> typing.Any:
|
||||
"""执行工具调用"""
|
||||
execution_context = await self._assert_execution_active(
|
||||
_execution_context_from_query(query)
|
||||
)
|
||||
execution_context = await self._assert_execution_active(_execution_context_from_query(query))
|
||||
if source_id is None and name == MCP_TOOL_LIST_RESOURCES:
|
||||
if getattr(query, 'variables', {}).get('_pipeline_mcp_resource_agent_read_enabled', True) is not True:
|
||||
raise ToolExecutionDeniedError(name, 'MCP resource agent reads are disabled')
|
||||
|
||||
@@ -368,9 +368,7 @@ class ToolManager:
|
||||
return None
|
||||
return await self.plugin_tool_loader.get_tool(name, source_id=source_id)
|
||||
if source == 'mcp':
|
||||
return await self.mcp_tool_loader.get_tool(
|
||||
context, name, source_id=source_id
|
||||
)
|
||||
return await self.mcp_tool_loader.get_tool(context, name, source_id=source_id)
|
||||
return None
|
||||
|
||||
async def generate_tools_for_openai(self, use_funcs: list[resource_tool.LLMTool]) -> list:
|
||||
@@ -488,9 +486,7 @@ class ToolManager:
|
||||
if source_ref is not None:
|
||||
execution_context = get_query_execution_context(query)
|
||||
await self._bind_plugin_workspace(execution_context)
|
||||
sandbox_available = await self._workspace_sandbox_available(
|
||||
execution_context
|
||||
)
|
||||
sandbox_available = await self._workspace_sandbox_available(execution_context)
|
||||
source = source_ref['source']
|
||||
source_id = source_ref.get('source_id')
|
||||
uses_source_id = False
|
||||
|
||||
Reference in New Issue
Block a user