From ccb7128867a499f70af931bb3e084a280f7f0f31 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Sun, 12 Apr 2026 16:34:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0AGENTS.md=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B3=A8=E5=85=A5=E5=8A=9F=E8=83=BD=E5=92=8C=E6=A0=B9?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E6=96=87=E4=BB=B6=E5=88=9B=E5=BB=BA=E9=99=90?= =?UTF-8?q?=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/main_terminal.py | 2 +- core/main_terminal_parts/context.py | 37 +++++++++++++++++++++++++++++ modules/file_manager.py | 21 ++++++++++++++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/core/main_terminal.py b/core/main_terminal.py index 3a3aa95..69a8054 100644 --- a/core/main_terminal.py +++ b/core/main_terminal.py @@ -104,7 +104,7 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi ) self.container_session: Optional["ContainerHandle"] = None self.memory_manager = MemoryManager(data_dir=str(self.data_dir)) - self.file_manager = FileManager(project_path, container_session=container_session) + self.file_manager = FileManager(project_path, container_session=container_session, data_dir=str(self.data_dir)) self.search_engine = SearchEngine() self.terminal_ops = TerminalOperator(project_path, container_session=container_session) self.ocr_client = OCRClient(project_path, self.file_manager) diff --git a/core/main_terminal_parts/context.py b/core/main_terminal_parts/context.py index c87db11..48480de 100644 --- a/core/main_terminal_parts/context.py +++ b/core/main_terminal_parts/context.py @@ -208,6 +208,18 @@ class MainTerminalContextMixin: personalization_text = personalization_block messages.append({"role": "system", "content": personalization_text}) + # AGENTS.md 自动注入 + agents_md_inject_enabled = bool(personalization_config.get("agents_md_auto_inject", False)) if isinstance(personalization_config, dict) else False + if agents_md_inject_enabled: + agents_md_content = self._load_agents_md_content() + if agents_md_content: + agents_md_template = self.load_prompt("agents_md_inject").strip() + if agents_md_template and "{{AGENTS_MD_CONTENT}}" in agents_md_template: + agents_md_text = agents_md_template.replace("{{AGENTS_MD_CONTENT}}", agents_md_content) + else: + agents_md_text = f"【AGENTS.md 项目规范】\n\n{agents_md_content}\n\n---\n请注意:以上规范来自工作区根目录的 AGENTS.md 文件,若有冲突请以 AGENTS.md 为准。" + messages.append({"role": "system", "content": agents_md_text}) + # 支持按对话覆盖的自定义 system prompt(API 用途)。 # 放在最后一个 system 消息位置,确保优先级最高,便于业务场景强约束。 custom_system_prompt = getattr(self.context_manager, "custom_system_prompt", None) @@ -340,6 +352,31 @@ class MainTerminalContextMixin: print(f"[ContextCompression] build_messages 替换tool占位符: {replaced_tool_count} 条") return messages + def _load_agents_md_content(self) -> Optional[str]: + """加载工作区根目录的 AGENTS.md 文件内容。 + + 如果存在多个 AGENTS.md 文件,返回最新更新的那一个。 + """ + try: + project_path = Path(self.project_path) + if not project_path.exists(): + return None + + # 查找所有 AGENTS.md 文件 + agents_md_files = list(project_path.rglob("AGENTS.md")) + if not agents_md_files: + return None + + # 找到最新更新的文件 + latest_file = max(agents_md_files, key=lambda p: p.stat().st_mtime) + + # 读取文件内容 + content = latest_file.read_text(encoding='utf-8') + return content.strip() if content else None + except Exception as exc: + logger.warning(f"[AGENTS.md] 读取失败: {exc}") + return None + def load_prompt(self, name: str) -> str: """加载提示模板""" prompt_file = Path(PROMPTS_DIR) / f"{name}.txt" diff --git a/modules/file_manager.py b/modules/file_manager.py index c7c8a72..f4e0a1c 100644 --- a/modules/file_manager.py +++ b/modules/file_manager.py @@ -44,11 +44,22 @@ DISABLE_LENGTH_CHECK = True logger = setup_logger(__name__) class FileManager: - def __init__(self, project_path: str, container_session: Optional["ContainerHandle"] = None): + def __init__(self, project_path: str, container_session: Optional["ContainerHandle"] = None, data_dir: Optional[str] = None): self.project_path = Path(project_path).resolve() self.container_session: Optional["ContainerHandle"] = None self._container_proxy: Optional[ContainerFileProxy] = None + self._data_dir: Optional[str] = data_dir self.set_container_session(container_session) + + def _load_personalization_config(self) -> Optional[Dict]: + """加载个性化配置""" + if not self._data_dir: + return None + try: + from modules.personalization_manager import load_personalization_config + return load_personalization_config(self._data_dir) + except Exception: + return None def set_container_session(self, container_session: Optional["ContainerHandle"]): self.container_session = container_session @@ -191,7 +202,13 @@ class FileManager: relative_path = self._relative_path(full_path) try: - if full_path.parent == self.project_path: + # 检查是否允许在根目录创建文件 + personalization_config = self._load_personalization_config() + allow_root_creation = bool( + personalization_config.get("allow_root_file_creation", False) + ) if isinstance(personalization_config, dict) else False + + if full_path.parent == self.project_path and not allow_root_creation: return { "success": False, "error": "禁止在项目根目录直接创建文件,请先创建或选择合适的子目录。",