From 2235ab971c8cc6b3d29632dec12f96d762a85709 Mon Sep 17 00:00:00 2001 From: suluyan Date: Wed, 24 Dec 2025 20:55:20 +0800 Subject: [PATCH 01/10] feat: support mcp resources --- ms_agent/agent/llm_agent.py | 9 ++++++--- ms_agent/llm/openai_llm.py | 4 ++++ ms_agent/llm/utils.py | 24 ++++++++++++++++++++++++ ms_agent/tools/mcp_client.py | 8 ++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/ms_agent/agent/llm_agent.py b/ms_agent/agent/llm_agent.py index b47e3a65a..bdb1a4be2 100644 --- a/ms_agent/agent/llm_agent.py +++ b/ms_agent/agent/llm_agent.py @@ -12,7 +12,7 @@ from ms_agent.agent.runtime import Runtime from ms_agent.callbacks import Callback, callbacks_mapping from ms_agent.llm.llm import LLM -from ms_agent.llm.utils import Message +from ms_agent.llm.utils import Message, ToolResult from ms_agent.memory import Memory, get_memory_meta_safe, memory_mapping from ms_agent.memory.memory_manager import SharedMemoryManager from ms_agent.rag.base import RAG @@ -243,11 +243,14 @@ async def parallel_tool_call(self, assert len(tool_call_result) == len(messages[-1].tool_calls) for tool_call_result, tool_call_query in zip(tool_call_result, messages[-1].tool_calls): + tool_call_result_format = ToolResult.from_raw(tool_call_result) _new_message = Message( role='tool', - content=tool_call_result, + content=tool_call_result_format.text, tool_call_id=tool_call_query['id'], - name=tool_call_query['tool_name']) + name=tool_call_query['tool_name'], + resources=tool_call_result_format.resources) + if _new_message.tool_call_id is None: # If tool call id is None, add a random one _new_message.tool_call_id = str(uuid.uuid4())[:8] diff --git a/ms_agent/llm/openai_llm.py b/ms_agent/llm/openai_llm.py index 3d012619d..8f0810346 100644 --- a/ms_agent/llm/openai_llm.py +++ b/ms_agent/llm/openai_llm.py @@ -132,6 +132,10 @@ def _call_llm(self, """ messages = self._format_input_message(messages) + if kwargs.get('stream', False) and self.args.get( + 'stream_options', {}).get('include_usage', True): + kwargs['stream_options'] = {'include_usage': True} + return self.client.chat.completions.create( model=self.model, messages=messages, tools=tools, **kwargs) diff --git a/ms_agent/llm/utils.py b/ms_agent/llm/utils.py index 1a02e1034..61c4f05c4 100644 --- a/ms_agent/llm/utils.py +++ b/ms_agent/llm/utils.py @@ -46,6 +46,9 @@ class Message: partial: bool = False prefix: bool = False + # code block + resources: List[str] = field(default_factory=list) + # usage completion_tokens: int = 0 prompt_tokens: int = 0 @@ -78,3 +81,24 @@ def to_dict_clean(self): for key, value in raw_dict.items() if (value or key in required) and key not in rm } + + +@dataclass +class ToolResult: + text: str + resources: List[str] = None + extra: dict = None + + @staticmethod + def from_raw(raw): + if isinstance(raw, str): + return ToolResult(text=raw) + if isinstance(raw, dict): + return ToolResult( + text=str(raw.get('text', '')), + resources=raw.get('resources', []), + extra={ + k: v + for k, v in raw.items() if k not in ['text', 'resources'] + }) + raise TypeError('tool_call_result must be str or dict') diff --git a/ms_agent/tools/mcp_client.py b/ms_agent/tools/mcp_client.py index db7e56e25..cf7b8df9b 100644 --- a/ms_agent/tools/mcp_client.py +++ b/ms_agent/tools/mcp_client.py @@ -65,6 +65,7 @@ async def call_tool(self, server_name: str, tool_name: str, tool_name, tool_args) texts = [] + resources = [] if response.isError: sep = '\n\n' if all(isinstance(item, str) for item in response.content): @@ -77,6 +78,13 @@ async def call_tool(self, server_name: str, tool_name: str, for content in response.content: if content.type == 'text': texts.append(content.text) + elif content.type == 'resource': + texts.append(str(content.resource)) + resources.append(content.resource) + + if resources: + return {'text': '\n\n'.join(texts), 'resources': resources} + return '\n\n'.join(texts) async def get_tools(self) -> Dict: From 3502f48f20af131120900bb59dcbadccd4e87d07 Mon Sep 17 00:00:00 2001 From: suluyana <110878454+suluyana@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:00:50 +0800 Subject: [PATCH 02/10] Update ms_agent/llm/openai_llm.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- ms_agent/llm/openai_llm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ms_agent/llm/openai_llm.py b/ms_agent/llm/openai_llm.py index 8f0810346..ff5bb6744 100644 --- a/ms_agent/llm/openai_llm.py +++ b/ms_agent/llm/openai_llm.py @@ -134,7 +134,7 @@ def _call_llm(self, if kwargs.get('stream', False) and self.args.get( 'stream_options', {}).get('include_usage', True): - kwargs['stream_options'] = {'include_usage': True} + kwargs.setdefault('stream_options', {})['include_usage'] = True return self.client.chat.completions.create( model=self.model, messages=messages, tools=tools, **kwargs) From 7a00f6e168c54a71d327915e562cb54107408861 Mon Sep 17 00:00:00 2001 From: suluyana <110878454+suluyana@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:01:36 +0800 Subject: [PATCH 03/10] Update ms_agent/llm/utils.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- ms_agent/llm/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ms_agent/llm/utils.py b/ms_agent/llm/utils.py index 61c4f05c4..8d39c21bc 100644 --- a/ms_agent/llm/utils.py +++ b/ms_agent/llm/utils.py @@ -86,8 +86,8 @@ def to_dict_clean(self): @dataclass class ToolResult: text: str - resources: List[str] = None - extra: dict = None + resources: List[str] = field(default_factory=list) + extra: dict = field(default_factory=dict) @staticmethod def from_raw(raw): From 1930e515939d88e313f3204c4749189006a6a82b Mon Sep 17 00:00:00 2001 From: suluyana <110878454+suluyana@users.noreply.github.com> Date: Fri, 26 Dec 2025 14:01:46 +0800 Subject: [PATCH 04/10] Update ms_agent/tools/mcp_client.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- ms_agent/tools/mcp_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ms_agent/tools/mcp_client.py b/ms_agent/tools/mcp_client.py index cf7b8df9b..83430f86d 100644 --- a/ms_agent/tools/mcp_client.py +++ b/ms_agent/tools/mcp_client.py @@ -80,7 +80,7 @@ async def call_tool(self, server_name: str, tool_name: str, texts.append(content.text) elif content.type == 'resource': texts.append(str(content.resource)) - resources.append(content.resource) + resources.append(str(content.resource)) if resources: return {'text': '\n\n'.join(texts), 'resources': resources} From adae06104b4a34bbb1f50792d9a7963092228eaf Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 12:35:07 +0800 Subject: [PATCH 05/10] fix global import --- ms_agent/tools/findata/akshare_source.py | 52 +++++++++++-------- .../tools/image_generator/ms_image_gen.py | 2 +- .../tools/video_generator/ds_video_gen.py | 3 +- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/ms_agent/tools/findata/akshare_source.py b/ms_agent/tools/findata/akshare_source.py index ab2f898e9..b7a3937a8 100644 --- a/ms_agent/tools/findata/akshare_source.py +++ b/ms_agent/tools/findata/akshare_source.py @@ -2,7 +2,6 @@ import re from typing import Any, Dict, List, Optional -import pandas as pd from ms_agent.tools.findata.data_source_base import (DataSourceError, FinancialDataSource, NoDataFoundError) @@ -67,8 +66,8 @@ def _convert_date(self, date: str) -> str: """Convert date to AKShare format""" return date.replace('-', '') - def _standardize_columns(self, df: pd.DataFrame, - code: str) -> pd.DataFrame: + def _standardize_columns(self, df: 'pandas.DataFrame', + code: str) -> 'pandas.DataFrame': """Standardize column names for compatibility with BaoStock format""" if df.empty: return df @@ -112,7 +111,7 @@ def get_historical_k_data( frequency: str = 'd', adjust_flag: str = '3', fields: Optional[List[str]] = None, - ) -> pd.DataFrame: + ) -> 'pandas.DataFrame': """Get historical K-line data""" logger.info(f'Fetching K-data for {code} ({start_date} to {end_date})') @@ -186,7 +185,7 @@ def get_historical_k_data( except Exception as e: raise DataSourceError(f'Failed to fetch K-data: {e}') - def get_stock_basic_info(self, code: str) -> pd.DataFrame: + def get_stock_basic_info(self, code: str) -> 'pandas.DataFrame': """Get stock basic information""" logger.info(f'Fetching basic info for {code}') @@ -205,8 +204,10 @@ def get_stock_basic_info(self, code: str) -> pd.DataFrame: # Only wrap unexpected errors raise DataSourceError(f'Failed to fetch basic info: {e}') - def _get_hk_basic_info(self, code: str) -> pd.DataFrame: + def _get_hk_basic_info(self, code: str) -> 'pandas.DataFrame': """Get HK stock basic information""" + import pandas as pd + clean_code = self._convert_code(code, market='HK') df_stock_info = pd.DataFrame() df_business_info = pd.DataFrame() @@ -260,8 +261,9 @@ def _get_hk_basic_info(self, code: str) -> pd.DataFrame: return pd.concat([df_stock_info, df_business_info], axis=1) - def _get_us_basic_info(self, code: str) -> pd.DataFrame: + def _get_us_basic_info(self, code: str) -> 'pandas.DataFrame': """Get US stock basic information""" + import pandas as pd symbol = self._convert_code(code, 'US') try: @@ -287,8 +289,9 @@ def _get_us_basic_info(self, code: str) -> pd.DataFrame: raise DataSourceError( f'Error fetching US stock basic info for {code}: {e}') - def _get_a_share_basic_info(self, code: str) -> pd.DataFrame: + def _get_a_share_basic_info(self, code: str) -> 'pandas.DataFrame': """Get A-share stock basic information""" + import pandas as pd clean_code = self._convert_code(code, 'A') try: @@ -338,14 +341,14 @@ def _get_a_share_basic_info(self, code: str) -> pd.DataFrame: def get_dividend_data(self, code: str, year: Optional[str] = None, - year_type: str = 'report') -> pd.DataFrame: + year_type: str = 'report') -> 'pandas.DataFrame': """Dividend info is not provided via a unified endpoint across markets in AKShare.""" raise DataSourceError( 'get_dividend_data is not supported by AKShareDataSource; use BaoStock or Hybrid' ) def get_adjust_factor_data(self, code: str, start_date: str, - end_date: str) -> pd.DataFrame: + end_date: str) -> 'pandas.DataFrame': """Adjust factor via AKShare varies by function; not standardized here.""" raise DataSourceError( 'get_adjust_factor_data is not supported by AKShareDataSource; use BaoStock or Hybrid' @@ -359,6 +362,7 @@ def get_financial_data(self, code: str, year: str, quarter: int, logger.info( f'Fetching financial data for {code} ({year}Q{quarter}) {data_types}' ) + import pandas as pd if code.startswith(('hk.', 'us.')): logger.warning( @@ -554,17 +558,18 @@ def _filter_columns(row_df: pd.DataFrame, return result - def get_report(self, - code: str, - start_date: str, - end_date: str, - report_type: str = 'performance_express') -> pd.DataFrame: + def get_report( + self, + code: str, + start_date: str, + end_date: str, + report_type: str = 'performance_express') -> 'pandas.DataFrame': """Report data is not supported by AKShare.""" raise DataSourceError( 'get_report is not supported by AKShareDataSource; use BaoStock or Hybrid' ) - def get_stock_industry(self, code: str, date: str) -> pd.DataFrame: + def get_stock_industry(self, code: str, date: str) -> 'pandas.DataFrame': """Industry classification is not supported by AKShare.""" raise DataSourceError( 'get_stock_industry is not supported by AKShareDataSource; use BaoStock or Hybrid' @@ -572,7 +577,7 @@ def get_stock_industry(self, code: str, date: str) -> pd.DataFrame: def get_stock_list(self, date: str, - data_type: str = 'all_a_share') -> pd.DataFrame: + data_type: str = 'all_a_share') -> 'pandas.DataFrame': """Get stock list (A-shares only, index constituents not supported).""" logger.info( f'Fetching stock list for {data_type}, only support a_share and latest data' @@ -598,7 +603,7 @@ def get_stock_list(self, def get_trade_dates(self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> pd.DataFrame: + end_date: Optional[str] = None) -> 'pandas.DataFrame': """Get trading calendar""" logger.info(f'Fetching trade dates ({start_date} to {end_date})') @@ -624,9 +629,10 @@ def get_macro_data( start_date: str, end_date: str, data_types: Optional[List[str]] = None, - extra_kwargs: Optional[Dict[str, - Any]] = None) -> Dict[str, pd.DataFrame]: + extra_kwargs: Optional[Dict[str, Any]] = None + ) -> Dict[str, 'pandas.DataFrame']: """Macroeconomic data.""" + import pandas as pd if data_types is None: data_types = [] if extra_kwargs is None: @@ -669,7 +675,8 @@ def get_macro_data( def _get_money_supply_data_month( self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> pd.DataFrame: + end_date: Optional[str] = None) -> 'pandas.DataFrame': + import pandas as pd try: df = akshare.macro_china_money_supply() # from 2008-01 to now df['月份'] = pd.to_datetime(df['月份'].str.replace('月份', @@ -690,7 +697,8 @@ def _get_money_supply_data_month( def _get_money_supply_data_year( self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> pd.DataFrame: + end_date: Optional[str] = None) -> 'pandas.DataFrame': + import pandas as pd month_df = self._get_money_supply_data_month() # Take the last issue of each year (usually December; if missing, take the last available entry of that year). month_df['年'] = month_df['月份'].dt.year diff --git a/ms_agent/tools/image_generator/ms_image_gen.py b/ms_agent/tools/image_generator/ms_image_gen.py index 648a10b3b..b121458e6 100644 --- a/ms_agent/tools/image_generator/ms_image_gen.py +++ b/ms_agent/tools/image_generator/ms_image_gen.py @@ -3,7 +3,6 @@ import uuid from io import BytesIO -import aiohttp import json from PIL import Image @@ -20,6 +19,7 @@ async def generate_image(self, negative_prompt=None, size=None, **kwargs): + import aiohttp image_generator = self.config.tools.image_generator base_url = (getattr(image_generator, 'base_url', None) or 'https://api-inference.modelscope.cn').strip('/') diff --git a/ms_agent/tools/video_generator/ds_video_gen.py b/ms_agent/tools/video_generator/ds_video_gen.py index fbdc38870..d757038d3 100644 --- a/ms_agent/tools/video_generator/ds_video_gen.py +++ b/ms_agent/tools/video_generator/ds_video_gen.py @@ -2,7 +2,6 @@ import os import uuid -import aiohttp from ms_agent.utils import get_logger logger = get_logger() @@ -34,6 +33,7 @@ async def generate_video(self, @staticmethod async def download_video(video_url, output_file): + import aiohttp max_retries = 3 retry_count = 0 @@ -57,6 +57,7 @@ async def download_video(video_url, output_file): @staticmethod async def _generate_video(base_url, api_key, model, prompt, size, seconds): + import aiohttp base_url = base_url.strip('/') create_endpoint = '/api/v1/services/aigc/model-evaluation/async-inference/' From 21049b1137804b6cc5c944ee574cf6f58d9f0dfe Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 15:11:58 +0800 Subject: [PATCH 06/10] Revert "fix global import" This reverts commit adae06104b4a34bbb1f50792d9a7963092228eaf. --- ms_agent/tools/findata/akshare_source.py | 52 ++++++++----------- .../tools/image_generator/ms_image_gen.py | 2 +- .../tools/video_generator/ds_video_gen.py | 3 +- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/ms_agent/tools/findata/akshare_source.py b/ms_agent/tools/findata/akshare_source.py index b7a3937a8..ab2f898e9 100644 --- a/ms_agent/tools/findata/akshare_source.py +++ b/ms_agent/tools/findata/akshare_source.py @@ -2,6 +2,7 @@ import re from typing import Any, Dict, List, Optional +import pandas as pd from ms_agent.tools.findata.data_source_base import (DataSourceError, FinancialDataSource, NoDataFoundError) @@ -66,8 +67,8 @@ def _convert_date(self, date: str) -> str: """Convert date to AKShare format""" return date.replace('-', '') - def _standardize_columns(self, df: 'pandas.DataFrame', - code: str) -> 'pandas.DataFrame': + def _standardize_columns(self, df: pd.DataFrame, + code: str) -> pd.DataFrame: """Standardize column names for compatibility with BaoStock format""" if df.empty: return df @@ -111,7 +112,7 @@ def get_historical_k_data( frequency: str = 'd', adjust_flag: str = '3', fields: Optional[List[str]] = None, - ) -> 'pandas.DataFrame': + ) -> pd.DataFrame: """Get historical K-line data""" logger.info(f'Fetching K-data for {code} ({start_date} to {end_date})') @@ -185,7 +186,7 @@ def get_historical_k_data( except Exception as e: raise DataSourceError(f'Failed to fetch K-data: {e}') - def get_stock_basic_info(self, code: str) -> 'pandas.DataFrame': + def get_stock_basic_info(self, code: str) -> pd.DataFrame: """Get stock basic information""" logger.info(f'Fetching basic info for {code}') @@ -204,10 +205,8 @@ def get_stock_basic_info(self, code: str) -> 'pandas.DataFrame': # Only wrap unexpected errors raise DataSourceError(f'Failed to fetch basic info: {e}') - def _get_hk_basic_info(self, code: str) -> 'pandas.DataFrame': + def _get_hk_basic_info(self, code: str) -> pd.DataFrame: """Get HK stock basic information""" - import pandas as pd - clean_code = self._convert_code(code, market='HK') df_stock_info = pd.DataFrame() df_business_info = pd.DataFrame() @@ -261,9 +260,8 @@ def _get_hk_basic_info(self, code: str) -> 'pandas.DataFrame': return pd.concat([df_stock_info, df_business_info], axis=1) - def _get_us_basic_info(self, code: str) -> 'pandas.DataFrame': + def _get_us_basic_info(self, code: str) -> pd.DataFrame: """Get US stock basic information""" - import pandas as pd symbol = self._convert_code(code, 'US') try: @@ -289,9 +287,8 @@ def _get_us_basic_info(self, code: str) -> 'pandas.DataFrame': raise DataSourceError( f'Error fetching US stock basic info for {code}: {e}') - def _get_a_share_basic_info(self, code: str) -> 'pandas.DataFrame': + def _get_a_share_basic_info(self, code: str) -> pd.DataFrame: """Get A-share stock basic information""" - import pandas as pd clean_code = self._convert_code(code, 'A') try: @@ -341,14 +338,14 @@ def _get_a_share_basic_info(self, code: str) -> 'pandas.DataFrame': def get_dividend_data(self, code: str, year: Optional[str] = None, - year_type: str = 'report') -> 'pandas.DataFrame': + year_type: str = 'report') -> pd.DataFrame: """Dividend info is not provided via a unified endpoint across markets in AKShare.""" raise DataSourceError( 'get_dividend_data is not supported by AKShareDataSource; use BaoStock or Hybrid' ) def get_adjust_factor_data(self, code: str, start_date: str, - end_date: str) -> 'pandas.DataFrame': + end_date: str) -> pd.DataFrame: """Adjust factor via AKShare varies by function; not standardized here.""" raise DataSourceError( 'get_adjust_factor_data is not supported by AKShareDataSource; use BaoStock or Hybrid' @@ -362,7 +359,6 @@ def get_financial_data(self, code: str, year: str, quarter: int, logger.info( f'Fetching financial data for {code} ({year}Q{quarter}) {data_types}' ) - import pandas as pd if code.startswith(('hk.', 'us.')): logger.warning( @@ -558,18 +554,17 @@ def _filter_columns(row_df: pd.DataFrame, return result - def get_report( - self, - code: str, - start_date: str, - end_date: str, - report_type: str = 'performance_express') -> 'pandas.DataFrame': + def get_report(self, + code: str, + start_date: str, + end_date: str, + report_type: str = 'performance_express') -> pd.DataFrame: """Report data is not supported by AKShare.""" raise DataSourceError( 'get_report is not supported by AKShareDataSource; use BaoStock or Hybrid' ) - def get_stock_industry(self, code: str, date: str) -> 'pandas.DataFrame': + def get_stock_industry(self, code: str, date: str) -> pd.DataFrame: """Industry classification is not supported by AKShare.""" raise DataSourceError( 'get_stock_industry is not supported by AKShareDataSource; use BaoStock or Hybrid' @@ -577,7 +572,7 @@ def get_stock_industry(self, code: str, date: str) -> 'pandas.DataFrame': def get_stock_list(self, date: str, - data_type: str = 'all_a_share') -> 'pandas.DataFrame': + data_type: str = 'all_a_share') -> pd.DataFrame: """Get stock list (A-shares only, index constituents not supported).""" logger.info( f'Fetching stock list for {data_type}, only support a_share and latest data' @@ -603,7 +598,7 @@ def get_stock_list(self, def get_trade_dates(self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> 'pandas.DataFrame': + end_date: Optional[str] = None) -> pd.DataFrame: """Get trading calendar""" logger.info(f'Fetching trade dates ({start_date} to {end_date})') @@ -629,10 +624,9 @@ def get_macro_data( start_date: str, end_date: str, data_types: Optional[List[str]] = None, - extra_kwargs: Optional[Dict[str, Any]] = None - ) -> Dict[str, 'pandas.DataFrame']: + extra_kwargs: Optional[Dict[str, + Any]] = None) -> Dict[str, pd.DataFrame]: """Macroeconomic data.""" - import pandas as pd if data_types is None: data_types = [] if extra_kwargs is None: @@ -675,8 +669,7 @@ def get_macro_data( def _get_money_supply_data_month( self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> 'pandas.DataFrame': - import pandas as pd + end_date: Optional[str] = None) -> pd.DataFrame: try: df = akshare.macro_china_money_supply() # from 2008-01 to now df['月份'] = pd.to_datetime(df['月份'].str.replace('月份', @@ -697,8 +690,7 @@ def _get_money_supply_data_month( def _get_money_supply_data_year( self, start_date: Optional[str] = None, - end_date: Optional[str] = None) -> 'pandas.DataFrame': - import pandas as pd + end_date: Optional[str] = None) -> pd.DataFrame: month_df = self._get_money_supply_data_month() # Take the last issue of each year (usually December; if missing, take the last available entry of that year). month_df['年'] = month_df['月份'].dt.year diff --git a/ms_agent/tools/image_generator/ms_image_gen.py b/ms_agent/tools/image_generator/ms_image_gen.py index b121458e6..648a10b3b 100644 --- a/ms_agent/tools/image_generator/ms_image_gen.py +++ b/ms_agent/tools/image_generator/ms_image_gen.py @@ -3,6 +3,7 @@ import uuid from io import BytesIO +import aiohttp import json from PIL import Image @@ -19,7 +20,6 @@ async def generate_image(self, negative_prompt=None, size=None, **kwargs): - import aiohttp image_generator = self.config.tools.image_generator base_url = (getattr(image_generator, 'base_url', None) or 'https://api-inference.modelscope.cn').strip('/') diff --git a/ms_agent/tools/video_generator/ds_video_gen.py b/ms_agent/tools/video_generator/ds_video_gen.py index d757038d3..fbdc38870 100644 --- a/ms_agent/tools/video_generator/ds_video_gen.py +++ b/ms_agent/tools/video_generator/ds_video_gen.py @@ -2,6 +2,7 @@ import os import uuid +import aiohttp from ms_agent.utils import get_logger logger = get_logger() @@ -33,7 +34,6 @@ async def generate_video(self, @staticmethod async def download_video(video_url, output_file): - import aiohttp max_retries = 3 retry_count = 0 @@ -57,7 +57,6 @@ async def download_video(video_url, output_file): @staticmethod async def _generate_video(base_url, api_key, model, prompt, size, seconds): - import aiohttp base_url = base_url.strip('/') create_endpoint = '/api/v1/services/aigc/model-evaluation/async-inference/' From 872df1a700c9a936d88a3a0799a6d92792abf370 Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 15:16:06 +0800 Subject: [PATCH 07/10] fix global import --- ms_agent/tools/tool_manager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ms_agent/tools/tool_manager.py b/ms_agent/tools/tool_manager.py index 290d0960b..edeccd052 100644 --- a/ms_agent/tools/tool_manager.py +++ b/ms_agent/tools/tool_manager.py @@ -13,12 +13,9 @@ from ms_agent.tools.base import ToolBase from ms_agent.tools.code import CodeExecutionTool, LocalCodeExecutionTool from ms_agent.tools.filesystem_tool import FileSystemTool -from ms_agent.tools.findata.findata_fetcher import FinancialDataFetcher -from ms_agent.tools.image_generator import ImageGenerator from ms_agent.tools.mcp_client import MCPClient from ms_agent.tools.shell.shell import Shell from ms_agent.tools.split_task import SplitTask -from ms_agent.tools.video_generator import VideoGenerator from ms_agent.utils import get_logger from ms_agent.utils.constants import TOOL_PLUGIN_NAME @@ -49,9 +46,11 @@ def __init__(self, self.extra_tools.append(SplitTask(config)) if hasattr(config, 'tools') and hasattr(config.tools, 'image_generator'): + from ms_agent.tools.image_generator import ImageGenerator self.extra_tools.append(ImageGenerator(config)) if hasattr(config, 'tools') and hasattr(config.tools, 'video_generator'): + from ms_agent.tools.video_generator import VideoGenerator self.extra_tools.append(VideoGenerator(config)) if hasattr(config, 'tools') and hasattr(config.tools, 'shell'): self.extra_tools.append(Shell(config)) @@ -76,6 +75,7 @@ def __init__(self, self.extra_tools.append(CodeExecutionTool(config)) if hasattr(config, 'tools') and hasattr(config.tools, 'financial_data_fetcher'): + from ms_agent.tools.findata.findata_fetcher import FinancialDataFetcher self.extra_tools.append(FinancialDataFetcher(config)) self.tool_call_timeout = getattr(config, 'tool_call_timeout', TOOL_CALL_TIMEOUT) From 86b86ec4e9988c745328ddcfb5b07510efcd81e1 Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 16:01:18 +0800 Subject: [PATCH 08/10] fix jsonify --- ms_agent/tools/mcp_client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ms_agent/tools/mcp_client.py b/ms_agent/tools/mcp_client.py index 83430f86d..f11b5c779 100644 --- a/ms_agent/tools/mcp_client.py +++ b/ms_agent/tools/mcp_client.py @@ -79,8 +79,9 @@ async def call_tool(self, server_name: str, tool_name: str, if content.type == 'text': texts.append(content.text) elif content.type == 'resource': - texts.append(str(content.resource)) - resources.append(str(content.resource)) + json_str = content.resource.model_dump_json(by_alias=True) + texts.append(json_str) + resources.append(json_str) if resources: return {'text': '\n\n'.join(texts), 'resources': resources} From dcda8683e5e9cab837ea870a24b9c83448b46e57 Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 16:45:48 +0800 Subject: [PATCH 09/10] fix twice json --- ms_agent/tools/mcp_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ms_agent/tools/mcp_client.py b/ms_agent/tools/mcp_client.py index f11b5c779..fab73db96 100644 --- a/ms_agent/tools/mcp_client.py +++ b/ms_agent/tools/mcp_client.py @@ -79,9 +79,10 @@ async def call_tool(self, server_name: str, tool_name: str, if content.type == 'text': texts.append(content.text) elif content.type == 'resource': + import json5 json_str = content.resource.model_dump_json(by_alias=True) texts.append(json_str) - resources.append(json_str) + resources.append(json5.loads(json_str)) if resources: return {'text': '\n\n'.join(texts), 'resources': resources} From c35fbaaf6f3d867c57cf27a2d5ad43f2167148de Mon Sep 17 00:00:00 2001 From: suluyan Date: Fri, 16 Jan 2026 17:16:50 +0800 Subject: [PATCH 10/10] fix typo --- ms_agent/llm/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ms_agent/llm/utils.py b/ms_agent/llm/utils.py index 8d39c21bc..be2eaf40e 100644 --- a/ms_agent/llm/utils.py +++ b/ms_agent/llm/utils.py @@ -46,8 +46,8 @@ class Message: partial: bool = False prefix: bool = False - # code block - resources: List[str] = field(default_factory=list) + # UI resources from mcp result + resources: List[Dict[str, str]] = field(default_factory=list) # usage completion_tokens: int = 0