diff --git a/astrbot/core/astr_main_agent.py b/astrbot/core/astr_main_agent.py index 1ea36ff7a..dfec4b94a 100644 --- a/astrbot/core/astr_main_agent.py +++ b/astrbot/core/astr_main_agent.py @@ -830,6 +830,38 @@ def _get_compress_provider( return provider +def _apply_global_context_info(event: AstrMessageEvent, req: ProviderRequest) -> None: + """Add platform and session information to user prompt when in global unified context mode.""" + from astrbot.core.config.default import ( + GLOBAL_UNIFIED_CONTEXT_UMO, + ORIGINAL_UMO_KEY, + ) + + if event.unified_msg_origin != GLOBAL_UNIFIED_CONTEXT_UMO: + return + + # Get original UMO from extras + original_umo = event.get_extra(ORIGINAL_UMO_KEY) + if not original_umo: + return + + # Parse the original UMO to extract platform, message type, and session info + try: + parts = original_umo.split(":", 2) + if len(parts) != 3: + logger.warning( + f"Original UMO format is invalid (expected 3 parts): {original_umo}" + ) + return + + platform_id, message_type, session_id = parts + context_info = f"[Context: Platform={platform_id}, Type={message_type}, Session={session_id}]" + # Prepend context info to the user prompt + req.prompt = f"{context_info} {req.prompt or ''}" + except Exception as e: + logger.warning(f"Failed to parse original UMO for global context: {e}") + + async def build_main_agent( *, event: AstrMessageEvent, @@ -888,6 +920,9 @@ async def build_main_agent( if isinstance(req.contexts, str): req.contexts = json.loads(req.contexts) + # Apply global context information if enabled + _apply_global_context_info(event, req) + if config.file_extract_enabled: try: await _apply_file_extract(event, req, config) diff --git a/astrbot/core/astr_main_agent_resources.py b/astrbot/core/astr_main_agent_resources.py index 1d5c085ce..c989c91bc 100644 --- a/astrbot/core/astr_main_agent_resources.py +++ b/astrbot/core/astr_main_agent_resources.py @@ -212,6 +212,10 @@ class SendMessageToUserTool(FunctionTool[AstrAgentContext]): "required": ["type"], }, }, + "session": { + "type": "string", + "description": "Target session ID in format 'platform:type:session_id'. If not specified, sends to the current session.", + }, }, "required": ["messages"], } @@ -253,7 +257,12 @@ async def _resolve_path_from_sandbox( async def call( self, context: ContextWrapper[AstrAgentContext], **kwargs ) -> ToolExecResult: - session = kwargs.get("session") or context.context.event.unified_msg_origin + # In global context mode, default to original UMO if session not specified + from astrbot.core.config.default import ORIGINAL_UMO_KEY + + original_umo = context.context.event.get_extra(ORIGINAL_UMO_KEY) + default_session = original_umo or context.context.event.unified_msg_origin + session = kwargs.get("session") or default_session messages = kwargs.get("messages") if not isinstance(messages, list) or not messages: diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 12056a04e..0a3bb42fb 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -17,11 +17,17 @@ "lark", ] +# Constant UMO for global unified context mode +GLOBAL_UNIFIED_CONTEXT_UMO = "global::global" +# Key for storing original UMO in event extras when global context mode is enabled +ORIGINAL_UMO_KEY = "original_umo" + # 默认配置 DEFAULT_CONFIG = { "config_version": 2, "platform_settings": { "unique_session": False, + "global_unified_context_mode": False, "rate_limit": { "time": 60, "count": 30, diff --git a/astrbot/core/pipeline/respond/stage.py b/astrbot/core/pipeline/respond/stage.py index 60ab168b3..3e8a5a916 100644 --- a/astrbot/core/pipeline/respond/stage.py +++ b/astrbot/core/pipeline/respond/stage.py @@ -169,6 +169,16 @@ async def process( f"Prepare to send - {event.get_sender_name()}/{event.get_sender_id()}: {event._outline_chain(result.chain)}", ) + # Restore original UMO before sending if in global context mode + from astrbot.core.config.default import ORIGINAL_UMO_KEY + + original_umo = event.get_extra(ORIGINAL_UMO_KEY) + if original_umo: + logger.debug( + f"Restoring original UMO before sending: {event.unified_msg_origin} -> {original_umo}" + ) + event.unified_msg_origin = original_umo + if result.result_content_type == ResultContentType.STREAMING_RESULT: if result.async_stream is None: logger.warning("async_stream 为空,跳过发送。") diff --git a/astrbot/core/pipeline/waking_check/stage.py b/astrbot/core/pipeline/waking_check/stage.py index 2dcb840e9..4fa412652 100644 --- a/astrbot/core/pipeline/waking_check/stage.py +++ b/astrbot/core/pipeline/waking_check/stage.py @@ -72,11 +72,29 @@ async def initialize(self, ctx: PipelineContext) -> None: ) platform_settings = self.ctx.astrbot_config.get("platform_settings", {}) self.unique_session = platform_settings.get("unique_session", False) + self.global_unified_context_mode = platform_settings.get( + "global_unified_context_mode", False + ) async def process( self, event: AstrMessageEvent, ) -> None | AsyncGenerator[None, None]: + # apply global unified context mode + if self.global_unified_context_mode: + from astrbot.core.config.default import ( + GLOBAL_UNIFIED_CONTEXT_UMO, + ORIGINAL_UMO_KEY, + ) + + original_umo = event.unified_msg_origin + event.unified_msg_origin = GLOBAL_UNIFIED_CONTEXT_UMO + # Store original UMO for reference in later stages + event.set_extra(ORIGINAL_UMO_KEY, original_umo) + logger.debug( + f"Global unified context mode enabled. Changed UMO from {original_umo} to {GLOBAL_UNIFIED_CONTEXT_UMO}" + ) + # apply unique session if self.unique_session and event.message_obj.type == MessageType.GROUP_MESSAGE: sid = build_unique_session_id(event) diff --git a/dashboard/src/theme/DarkTheme.ts b/dashboard/src/theme/DarkTheme.ts index 177bee39c..ab9ae8737 100644 --- a/dashboard/src/theme/DarkTheme.ts +++ b/dashboard/src/theme/DarkTheme.ts @@ -4,12 +4,12 @@ const PurpleThemeDark: ThemeTypes = { name: 'PurpleThemeDark', dark: true, variables: { - 'border-color': '#1677ff', + 'border-color': '#3c96ca', 'carousel-control-size': 10 }, colors: { - primary: '#1677ff', - secondary: '#722ed1', + primary: '#3c96ca', + secondary: '#2288b7', info: '#03c9d7', success: '#52c41a', accent: '#FFAB91',