From 0a71747eecd1d317a74471a7ae07267f2796c818 Mon Sep 17 00:00:00 2001 From: huanghuoguoguo <60681390+huanghuoguoguo@users.noreply.github.com> Date: Sun, 14 Jun 2026 21:20:31 +0800 Subject: [PATCH] chore(agent-runner): remove split-out incidental fixes --- .../http/controller/groups/resources/mcp.py | 6 +-- src/langbot/pkg/api/http/service/mcp.py | 2 +- .../8f24d6c9b1a0_ensure_mcp_readme_column.py | 37 ------------------- src/langbot/pkg/plugin/connector.py | 25 ++++--------- src/langbot/pkg/provider/modelmgr/modelmgr.py | 14 +------ .../persistence/test_migrations.py | 37 ------------------- .../unit_tests/plugin/test_connector_pure.py | 24 ------------ .../unit_tests/provider/test_model_service.py | 23 ------------ .../home/components/survey/SurveyWidget.tsx | 13 +------ 9 files changed, 14 insertions(+), 167 deletions(-) delete mode 100644 src/langbot/pkg/persistence/alembic/versions/8f24d6c9b1a0_ensure_mcp_readme_column.py diff --git a/src/langbot/pkg/api/http/controller/groups/resources/mcp.py b/src/langbot/pkg/api/http/controller/groups/resources/mcp.py index 0365cb0d..e6bc2e77 100644 --- a/src/langbot/pkg/api/http/controller/groups/resources/mcp.py +++ b/src/langbot/pkg/api/http/controller/groups/resources/mcp.py @@ -12,7 +12,7 @@ class MCPRouterGroup(group.RouterGroup): async def initialize(self) -> None: @self.route('/servers', methods=['GET', 'POST'], auth_type=group.AuthType.USER_TOKEN) async def _() -> str: - """List MCP servers or create a new MCP server.""" + """获取MCP服务器列表""" if quart.request.method == 'GET': servers = await self.ap.mcp_service.get_mcp_servers(contain_runtime_info=True) @@ -30,7 +30,7 @@ class MCPRouterGroup(group.RouterGroup): @self.route('/servers/', methods=['GET', 'PUT', 'DELETE'], auth_type=group.AuthType.USER_TOKEN) async def _(server_name: str) -> str: - """Get, update, or delete an MCP server configuration.""" + """获取、更新或删除MCP服务器配置""" from urllib.parse import unquote server_name = unquote(server_name) @@ -59,7 +59,7 @@ class MCPRouterGroup(group.RouterGroup): @self.route('/servers//test', methods=['POST'], auth_type=group.AuthType.USER_TOKEN) async def _(server_name: str) -> str: - """Test an MCP server connection.""" + """测试MCP服务器连接""" from urllib.parse import unquote server_name = unquote(server_name) diff --git a/src/langbot/pkg/api/http/service/mcp.py b/src/langbot/pkg/api/http/service/mcp.py index f9a48d2e..e0c64b9f 100644 --- a/src/langbot/pkg/api/http/service/mcp.py +++ b/src/langbot/pkg/api/http/service/mcp.py @@ -137,7 +137,7 @@ class MCPService: await self.ap.tool_mgr.mcp_tool_loader.remove_mcp_server(server_name) async def test_mcp_server(self, server_name: str, server_data: dict) -> int: - """Test an MCP server connection and return the task ID.""" + """测试 MCP 服务器连接并返回任务 ID""" runtime_mcp_session: RuntimeMCPSession | None = None diff --git a/src/langbot/pkg/persistence/alembic/versions/8f24d6c9b1a0_ensure_mcp_readme_column.py b/src/langbot/pkg/persistence/alembic/versions/8f24d6c9b1a0_ensure_mcp_readme_column.py deleted file mode 100644 index e859c74a..00000000 --- a/src/langbot/pkg/persistence/alembic/versions/8f24d6c9b1a0_ensure_mcp_readme_column.py +++ /dev/null @@ -1,37 +0,0 @@ -"""ensure mcp_servers readme column exists - -Revision ID: 8f24d6c9b1a0 -Revises: 7b2c1d9e4f30 -Create Date: 2026-06-13 -""" - -from alembic import op -import sqlalchemy as sa - - -revision = '8f24d6c9b1a0' -down_revision = '7b2c1d9e4f30' -branch_labels = None -depends_on = None - - -def _table_exists(table_name: str) -> bool: - return table_name in sa.inspect(op.get_bind()).get_table_names() - - -def _column_exists(table_name: str, column_name: str) -> bool: - return column_name in {column['name'] for column in sa.inspect(op.get_bind()).get_columns(table_name)} - - -def upgrade() -> None: - if not _table_exists('mcp_servers') or _column_exists('mcp_servers', 'readme'): - return - with op.batch_alter_table('mcp_servers', schema=None) as batch_op: - batch_op.add_column(sa.Column('readme', sa.Text(), nullable=False, server_default='')) - - -def downgrade() -> None: - if not _table_exists('mcp_servers') or not _column_exists('mcp_servers', 'readme'): - return - with op.batch_alter_table('mcp_servers', schema=None) as batch_op: - batch_op.drop_column('readme') diff --git a/src/langbot/pkg/plugin/connector.py b/src/langbot/pkg/plugin/connector.py index 506abd6c..9b285041 100644 --- a/src/langbot/pkg/plugin/connector.py +++ b/src/langbot/pkg/plugin/connector.py @@ -206,11 +206,10 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): self, file_bytes: bytes, task_context: taskmgr.TaskContext | None, - ) -> tuple[str | None, str | None, str | None]: + ) -> tuple[str | None, str | None]: """Extract plugin identity and dependency metadata from a plugin package.""" plugin_author = None plugin_name = None - plugin_version = None try: with zipfile.ZipFile(io.BytesIO(file_bytes)) as zf: @@ -219,7 +218,6 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): metadata = manifest.get('metadata', {}) plugin_author = metadata.get('author') plugin_name = metadata.get('name') - plugin_version = metadata.get('version') except Exception: pass @@ -238,7 +236,7 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): except Exception: pass - return plugin_author, plugin_name, plugin_version + return plugin_author, plugin_name async def _install_mcp_from_marketplace( self, @@ -377,10 +375,9 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): install_source: PluginInstallSource, install_info: dict[str, Any], task_context: taskmgr.TaskContext | None = None, - ): + ): plugin_author = install_info.get('plugin_author') plugin_name = install_info.get('plugin_name') - plugin_file_transferred = False if install_source == PluginInstallSource.MARKETPLACE: # Handle marketplace plugin/mcp/skill installation @@ -475,18 +472,14 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): ) file_bytes = download_resp.content - plugin_author, plugin_name, plugin_version = self._inspect_plugin_package( + plugin_author, plugin_name = self._inspect_plugin_package( file_bytes, task_context, ) if task_context is not None and plugin_author and plugin_name: task_context.metadata['plugin_name'] = f'{plugin_author}/{plugin_name}' - if task_context is not None and plugin_version: - task_context.metadata['plugin_version'] = plugin_version file_key = await self.handler.send_file(file_bytes, 'lbpkg') install_info['plugin_file_key'] = file_key - install_source = PluginInstallSource.LOCAL - plugin_file_transferred = True self.ap.logger.info(f'Transfered file {file_key} to plugin runtime') # Continue to install via runtime else: @@ -502,14 +495,12 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): mcp_resp.raise_for_status() raise Exception(f'Failed to get MCP {plugin_author}/{plugin_name}') - if install_source == PluginInstallSource.LOCAL and not plugin_file_transferred: + if install_source == PluginInstallSource.LOCAL: # transfer file before install file_bytes = install_info['plugin_file'] - plugin_author, plugin_name, plugin_version = self._inspect_plugin_package(file_bytes, task_context) + plugin_author, plugin_name = self._inspect_plugin_package(file_bytes, task_context) if task_context is not None and plugin_author and plugin_name: task_context.metadata['plugin_name'] = f'{plugin_author}/{plugin_name}' - if task_context is not None and plugin_version: - task_context.metadata['plugin_version'] = plugin_version file_key = await self.handler.send_file(file_bytes, 'lbpkg') install_info['plugin_file_key'] = file_key del install_info['plugin_file'] @@ -546,11 +537,9 @@ class PluginRuntimeConnector(ManagedRuntimeConnector): task_context.metadata['download_speed'] = downloaded / elapsed if elapsed > 0 else 0 file_bytes = b''.join(chunks) - plugin_author, plugin_name, plugin_version = self._inspect_plugin_package(file_bytes, task_context) + plugin_author, plugin_name = self._inspect_plugin_package(file_bytes, task_context) if task_context is not None and plugin_author and plugin_name: task_context.metadata['plugin_name'] = f'{plugin_author}/{plugin_name}' - if task_context is not None and plugin_version: - task_context.metadata['plugin_version'] = plugin_version file_key = await self.handler.send_file(file_bytes, 'lbpkg') install_info['plugin_file_key'] = file_key self.ap.logger.info(f'Transfered file {file_key} to plugin runtime') diff --git a/src/langbot/pkg/provider/modelmgr/modelmgr.py b/src/langbot/pkg/provider/modelmgr/modelmgr.py index 0b4fd2ed..0c577f1a 100644 --- a/src/langbot/pkg/provider/modelmgr/modelmgr.py +++ b/src/langbot/pkg/provider/modelmgr/modelmgr.py @@ -1,6 +1,5 @@ from __future__ import annotations -import asyncio import sqlalchemy import traceback @@ -85,19 +84,8 @@ class ModelManager: self.ap.logger.info('LangBot Space Models service is disabled, skipping sync.') return - sync_timeout = space_config.get('models_sync_timeout') try: - if sync_timeout: - await asyncio.wait_for( - self.sync_new_models_from_space(), - timeout=float(sync_timeout), - ) - else: - await self.sync_new_models_from_space() - except asyncio.TimeoutError: - self.ap.logger.warning( - f'LangBot Space model sync timed out after {sync_timeout}s, skipping startup sync.' - ) + await self.sync_new_models_from_space() except Exception as e: self.ap.logger.warning('Failed to sync new models from LangBot Space, model list may not be updated.') self.ap.logger.warning(f' - Error: {e}') diff --git a/tests/integration/persistence/test_migrations.py b/tests/integration/persistence/test_migrations.py index e576042c..26f9d912 100644 --- a/tests/integration/persistence/test_migrations.py +++ b/tests/integration/persistence/test_migrations.py @@ -11,7 +11,6 @@ from __future__ import annotations import pytest from alembic.script import ScriptDirectory -from sqlalchemy import inspect, text from sqlalchemy.ext.asyncio import create_async_engine from langbot.pkg.entity.persistence.base import Base @@ -148,42 +147,6 @@ class TestSQLiteMigrationUpgrade: rev2 = await get_alembic_current(sqlite_engine) assert rev2 == rev1, f"Expected {rev1}, got {rev2}" - @pytest.mark.asyncio - async def test_upgrade_repairs_head_stamped_mcp_readme_column(self, sqlite_engine): - """ - A database may already be stamped at the previous head while missing a - column added by an earlier guarded migration. Upgrade should still - repair mcp_servers.readme so startup ORM queries do not fail. - """ - async with sqlite_engine.begin() as conn: - await conn.execute( - text( - """ - CREATE TABLE mcp_servers ( - uuid VARCHAR(255) NOT NULL PRIMARY KEY, - name VARCHAR(255) NOT NULL, - enable BOOLEAN NOT NULL, - mode VARCHAR(255) NOT NULL, - extra_args JSON NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL - ) - """ - ) - ) - - await run_alembic_stamp(sqlite_engine, '7b2c1d9e4f30') - await run_alembic_upgrade(sqlite_engine, 'head') - - async with sqlite_engine.connect() as conn: - columns = await conn.run_sync( - lambda sync_conn: {column['name'] for column in inspect(sync_conn).get_columns('mcp_servers')} - ) - - assert 'readme' in columns - assert await get_alembic_current(sqlite_engine) == alembic_head_revision() - - class TestSQLiteMigrationFreshDatabase: """Tests for fresh database workflow.""" diff --git a/tests/unit_tests/plugin/test_connector_pure.py b/tests/unit_tests/plugin/test_connector_pure.py index 2b4515fd..13ba29b5 100644 --- a/tests/unit_tests/plugin/test_connector_pure.py +++ b/tests/unit_tests/plugin/test_connector_pure.py @@ -49,30 +49,6 @@ class TestExtractDepsMetadata: assert 'flask' in task_context.metadata['deps_list'] assert 'numpy' in task_context.metadata['deps_list'] - def test_extract_plugin_identity_includes_version(self): - """Extract plugin identity and version from manifest.yaml.""" - connector = self._create_connector() - - zip_buffer = io.BytesIO() - with zipfile.ZipFile(zip_buffer, 'w') as zf: - zf.writestr( - 'manifest.yaml', - '\n'.join( - [ - 'metadata:', - ' author: langbot-team', - ' name: LangRAG', - ' version: 0.1.8', - ] - ), - ) - - assert connector._inspect_plugin_package(zip_buffer.getvalue(), None) == ( - 'langbot-team', - 'LangRAG', - '0.1.8', - ) - def test_extract_deps_empty_requirements(self): """Handle empty requirements.txt.""" connector = self._create_connector() diff --git a/tests/unit_tests/provider/test_model_service.py b/tests/unit_tests/provider/test_model_service.py index c5cfd118..312746ee 100644 --- a/tests/unit_tests/provider/test_model_service.py +++ b/tests/unit_tests/provider/test_model_service.py @@ -1,6 +1,5 @@ from __future__ import annotations -import asyncio from types import SimpleNamespace from unittest.mock import AsyncMock, Mock @@ -115,28 +114,6 @@ def test_token_manager_next_token_ignores_empty_token_list(): assert token_mgr.using_token_index == 0 -@pytest.mark.asyncio -async def test_model_manager_initialize_skips_space_sync_after_timeout(): - ap = SimpleNamespace() - ap.discover = SimpleNamespace(get_components_by_kind=Mock(return_value=[])) - ap.instance_config = SimpleNamespace(data={'space': {'models_sync_timeout': 0.01}}) - ap.logger = Mock() - - mgr = ModelManager(ap) - mgr.load_models_from_db = AsyncMock() - - async def slow_sync(): - await asyncio.sleep(1) - - mgr.sync_new_models_from_space = AsyncMock(side_effect=slow_sync) - - await mgr.initialize() - - mgr.load_models_from_db.assert_awaited_once() - mgr.sync_new_models_from_space.assert_awaited_once() - ap.logger.warning.assert_any_call('LangBot Space model sync timed out after 0.01s, skipping startup sync.') - - @pytest.mark.asyncio async def test_updated_llm_model_is_immediately_usable_by_local_agent_pipeline(): from langbot.pkg.api.http.service.model import LLMModelsService diff --git a/web/src/app/home/components/survey/SurveyWidget.tsx b/web/src/app/home/components/survey/SurveyWidget.tsx index 16f35865..5e7dc06a 100644 --- a/web/src/app/home/components/survey/SurveyWidget.tsx +++ b/web/src/app/home/components/survey/SurveyWidget.tsx @@ -310,7 +310,6 @@ function SingleSelectField({ {options.map((opt) => (
{opt.has_input && selected && (