diff --git a/agent/prompt/builder.py b/agent/prompt/builder.py index d8f8401..91ef1c0 100644 --- a/agent/prompt/builder.py +++ b/agent/prompt/builder.py @@ -461,7 +461,7 @@ def _build_context_files_section(context_files: List[ContextFile], language: str def _build_runtime_section(runtime_info: Dict[str, Any], language: str) -> List[str]: - """构建运行时信息section""" + """构建运行时信息section - 支持动态时间""" if not runtime_info: return [] @@ -471,7 +471,17 @@ def _build_runtime_section(runtime_info: Dict[str, Any], language: str) -> List[ ] # Add current time if available - if runtime_info.get("current_time"): + # Support dynamic time via callable function + if callable(runtime_info.get("_get_current_time")): + try: + time_info = runtime_info["_get_current_time"]() + time_line = f"当前时间: {time_info['time']} {time_info['weekday']} ({time_info['timezone']})" + lines.append(time_line) + lines.append("") + except Exception as e: + logger.warning(f"[PromptBuilder] Failed to get dynamic time: {e}") + elif runtime_info.get("current_time"): + # Fallback to static time for backward compatibility time_str = runtime_info["current_time"] weekday = runtime_info.get("weekday", "") timezone = runtime_info.get("timezone", "") diff --git a/agent/protocol/agent.py b/agent/protocol/agent.py index 1b031e0..7d9baff 100644 --- a/agent/protocol/agent.py +++ b/agent/protocol/agent.py @@ -13,7 +13,8 @@ class Agent: def __init__(self, system_prompt: str, description: str = "AI Agent", model: LLMModel = None, tools=None, output_mode="print", max_steps=100, max_context_tokens=None, context_reserve_tokens=None, memory_manager=None, name: str = None, - workspace_dir: str = None, skill_manager=None, enable_skills: bool = True): + workspace_dir: str = None, skill_manager=None, enable_skills: bool = True, + runtime_info: dict = None): """ Initialize the Agent with system prompt, model, description. @@ -31,6 +32,7 @@ class Agent: :param workspace_dir: Optional workspace directory for workspace-specific skills :param skill_manager: Optional SkillManager instance (will be created if None and enable_skills=True) :param enable_skills: Whether to enable skills support (default: True) + :param runtime_info: Optional runtime info dict (with _get_current_time callable for dynamic time) """ self.name = name or "Agent" self.system_prompt = system_prompt @@ -48,6 +50,7 @@ class Agent: self.memory_manager = memory_manager # Memory manager for auto memory flush self.workspace_dir = workspace_dir # Workspace directory self.enable_skills = enable_skills # Skills enabled flag + self.runtime_info = runtime_info # Runtime info for dynamic time update # Initialize skill manager self.skill_manager = None @@ -105,9 +108,58 @@ class Agent: :return: Complete system prompt """ # Skills are now included in system_prompt by PromptBuilder - # No need to append them here + # If runtime_info contains dynamic time function, rebuild runtime section + if self.runtime_info and callable(self.runtime_info.get('_get_current_time')): + return self._rebuild_runtime_section(self.system_prompt) return self.system_prompt + def _rebuild_runtime_section(self, prompt: str) -> str: + """ + Rebuild runtime info section with current time. + + This method dynamically updates the runtime info section by calling + the _get_current_time function from runtime_info. + + :param prompt: Original system prompt + :return: Updated system prompt with current runtime info + """ + try: + # Get current time dynamically + time_info = self.runtime_info['_get_current_time']() + + # Build new runtime section + runtime_lines = [ + "\n## 运行时信息\n", + "\n", + f"当前时间: {time_info['time']} {time_info['weekday']} ({time_info['timezone']})\n", + "\n" + ] + + # Add other runtime info + runtime_parts = [] + if self.runtime_info.get("model"): + runtime_parts.append(f"模型={self.runtime_info['model']}") + if self.runtime_info.get("workspace"): + runtime_parts.append(f"工作空间={self.runtime_info['workspace']}") + if self.runtime_info.get("channel") and self.runtime_info.get("channel") != "web": + runtime_parts.append(f"渠道={self.runtime_info['channel']}") + + if runtime_parts: + runtime_lines.append("运行时: " + " | ".join(runtime_parts) + "\n") + runtime_lines.append("\n") + + new_runtime_section = "".join(runtime_lines) + + # Find and replace the runtime section + import re + pattern = r'\n## 运行时信息\s*\n.*?(?=\n##|\Z)' + updated_prompt = re.sub(pattern, new_runtime_section.rstrip('\n'), prompt, flags=re.DOTALL) + + return updated_prompt + except Exception as e: + logger.warning(f"Failed to rebuild runtime section: {e}") + return prompt + def refresh_skills(self): """Refresh the loaded skills.""" if self.skill_manager: diff --git a/bridge/agent_initializer.py b/bridge/agent_initializer.py index 27739b5..50de21b 100644 --- a/bridge/agent_initializer.py +++ b/bridge/agent_initializer.py @@ -110,7 +110,8 @@ class AgentInitializer: workspace_dir=workspace_root, skill_manager=skill_manager, enable_skills=True, - max_context_tokens=max_context_tokens + max_context_tokens=max_context_tokens, + runtime_info=runtime_info # Pass runtime_info for dynamic time updates ) # Attach memory manager @@ -289,34 +290,40 @@ class AgentInitializer: return None def _get_runtime_info(self, workspace_root: str): - """Get runtime information""" + """Get runtime information with dynamic time support""" from config import conf - now = datetime.datetime.now() - - # Get timezone info - try: - offset = -time.timezone if not time.daylight else -time.altzone - hours = offset // 3600 - minutes = (offset % 3600) // 60 - timezone_name = f"UTC{hours:+03d}:{minutes:02d}" if minutes else f"UTC{hours:+03d}" - except Exception: - timezone_name = "UTC" - - # Chinese weekday mapping - weekday_map = { - 'Monday': '星期一', 'Tuesday': '星期二', 'Wednesday': '星期三', - 'Thursday': '星期四', 'Friday': '星期五', 'Saturday': '星期六', 'Sunday': '星期日' - } - weekday_zh = weekday_map.get(now.strftime("%A"), now.strftime("%A")) + def get_current_time(): + """Get current time dynamically - called each time system prompt is accessed""" + now = datetime.datetime.now() + + # Get timezone info + try: + offset = -time.timezone if not time.daylight else -time.altzone + hours = offset // 3600 + minutes = (offset % 3600) // 60 + timezone_name = f"UTC{hours:+03d}:{minutes:02d}" if minutes else f"UTC{hours:+03d}" + except Exception: + timezone_name = "UTC" + + # Chinese weekday mapping + weekday_map = { + 'Monday': '星期一', 'Tuesday': '星期二', 'Wednesday': '星期三', + 'Thursday': '星期四', 'Friday': '星期五', 'Saturday': '星期六', 'Sunday': '星期日' + } + weekday_zh = weekday_map.get(now.strftime("%A"), now.strftime("%A")) + + return { + 'time': now.strftime("%Y-%m-%d %H:%M:%S"), + 'weekday': weekday_zh, + 'timezone': timezone_name + } return { "model": conf().get("model", "unknown"), "workspace": workspace_root, "channel": conf().get("channel_type", "unknown"), - "current_time": now.strftime("%Y-%m-%d %H:%M:%S"), - "weekday": weekday_zh, - "timezone": timezone_name + "_get_current_time": get_current_time # Dynamic time function } def _migrate_config_to_env(self, workspace_root: str):