From 47d284699065f0d71a0fb1710b157c2ad632736c Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 23 Aug 2026 01:28:08 +0800 Subject: [PATCH] refactor: inject agent runtime settings --- app/agent/runtime.py | 15 +++++++++++++-- docs/refactor/backend-architecture-next-stage.md | 3 ++- .../architecture/configuration-debt-baseline.json | 3 +-- .../architecture/dependency-baseline.json | 7 ++++--- tests/test_agent_runtime.py | 12 ++++++++++++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/app/agent/runtime.py b/app/agent/runtime.py index e97af2f6e..468bb4064 100644 --- a/app/agent/runtime.py +++ b/app/agent/runtime.py @@ -3,6 +3,7 @@ from __future__ import annotations import re +import importlib import shutil import threading import time @@ -12,7 +13,7 @@ from typing import Any, Iterable, Optional import yaml -from app.runtime.config import settings +from app.application.configuration import get_runtime_settings from app.runtime.log import logger CURRENT_PERSONA_FILE = "CURRENT_PERSONA.md" @@ -31,6 +32,16 @@ SUBAGENT_SCHEMA_VERSION = 1 DEFAULT_PERSONA_ID = "default" PERSONA_ID_PATTERN = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$") + +def _default_agent_root_dir() -> Path: + """从组合根设置服务取得 Agent 目录,导入早期保留旧设置回退。""" + try: + config_path = get_runtime_settings().get("CONFIG_PATH") + except RuntimeError: + legacy_settings = importlib.import_module("app.runtime.config").settings + config_path = legacy_settings.CONFIG_PATH + return Path(config_path) / "agent" + ROOT_LEVEL_RUNTIME_FILES = { CURRENT_PERSONA_FILE, } @@ -231,7 +242,7 @@ class AgentRuntimeManager: agent_root_dir: Optional[Path] = None, bundled_defaults_dir: Optional[Path] = None, ) -> None: - self.agent_root_dir = agent_root_dir or (settings.CONFIG_PATH / "agent") + self.agent_root_dir = agent_root_dir or _default_agent_root_dir() self.runtime_dir = self.agent_root_dir / SYSTEM_RUNTIME_DIR self.memory_dir = self.agent_root_dir / MEMORY_DIR self.skills_dir = self.agent_root_dir / SKILLS_DIR diff --git a/docs/refactor/backend-architecture-next-stage.md b/docs/refactor/backend-architecture-next-stage.md index 5cec767a8..3df6a0a0f 100644 --- a/docs/refactor/backend-architecture-next-stage.md +++ b/docs/refactor/backend-architecture-next-stage.md @@ -70,7 +70,7 @@ MoviePilot V3 当前不是“目录混乱、必须推倒重来”的状态。第 | legacy 默认模块契约 | 0 个宿主观察方法;未知动态方法保留 fallback | 所有静态宿主方法已有显式 V2 spec;真实 fallback 命中由 `module.contract.legacy_hit` 观测 | | 事件枚举 | 53 | 66 个静态 producer、15 个静态 consumer | | 专用 EventData model | 53 | Event Contract Registry 已为全部事件登记 typed payload/fallback 原因 | -| 直接读取 `settings` 的文件 | 122 | 仍按模块族迁移,动态协议和安全端口暂保留 | +| 直接读取 `settings` 的文件 | 121 | 仍按模块族迁移,动态协议和安全端口暂保留 | | `SystemConfigOper()` | 1 个 | 仅组合根创建 `SystemConfigService` 时保留 | | Model 上的 DB 查询装饰器 | 119 | `db_update`/`async_db_update` 为 0;查询 ABI 继续按 canonical 用例迁移 | | 路由端点 | 335 | 11 个已装饰端点超过 80 行,最大 400 行 | @@ -1018,6 +1018,7 @@ MFA/Passkey 专项测试与架构门禁通过,密钥类配置仍保留在安 2026-08-23 将 API 路由前缀作为组合根参数传入 `init_routers`,移除路由初始化模块对全局 `settings` 的直接读取;默认参数保留旧调用兼容性,并补充自定义前缀测试。配置债务由 125 个文件降至 124 个文件。 2026-08-23 将令牌编解码的密钥与过期策略接入 `TokenRuntimeConfig` 快照;启动组合根统一装配,未装配时保留 SDK/旧插件的动态回退,公开令牌函数签名不变。配置债务由 124 个文件降至 123 个文件,并补充资源/认证令牌回归测试。 2026-08-23 将 URL 资源签名改为复用 `TokenRuntimeConfig` 的资源密钥快照;未装配时保留旧模块动态回退,签名公开 API 与密钥轮换语义不变。配置债务由 123 个文件降至 122 个文件,并补充安全 URL、媒体服务器和字幕下载回归测试。 +2026-08-23 将 `AgentRuntimeManager` 的默认 Agent 目录改为通过 `RuntimeSettingsService` 读取配置快照;显式目录参数和导入早期的旧设置回退保持不变。配置债务由 122 个文件降至 121 个文件,并补充默认目录注入回归测试。 **收口记录(2026-08-22)**:`reidentify_cache`、`nettest`、`scrape`、OpenAI `chat_completions/responses`、`get_logging` 和 Web Agent SSE 均改为稳定公开入口委托私有编排实现;四个消息交互 Handler 的公开方法也保留 ABI 并委托私有状态机。复杂度基线已清零,API/Application/Chain 入口预算、异步阻塞 ratchet 均通过;复杂度及兼容专项合计 252 项测试通过。 随后将 `TransferChain.do_transfer` 的公开入口收口为稳定兼容 Facade,先提取媒体身份规范化阶段,保留显式 diff --git a/tests/fixtures/architecture/configuration-debt-baseline.json b/tests/fixtures/architecture/configuration-debt-baseline.json index 7ae37f367..475a27df3 100644 --- a/tests/fixtures/architecture/configuration-debt-baseline.json +++ b/tests/fixtures/architecture/configuration-debt-baseline.json @@ -9,7 +9,7 @@ "root": "app" }, "settings_imports": { - "count": 122, + "count": 121, "files": [ "app/adapters/cache/backends.py", "app/adapters/cache/redis.py", @@ -32,7 +32,6 @@ "app/agent/memory/__init__.py", "app/agent/orchestrator.py", "app/agent/prompt/__init__.py", - "app/agent/runtime.py", "app/agent/skills/registry.py", "app/agent/tools/base.py", "app/agent/tools/impl/_plugin_tool_utils.py", diff --git a/tests/fixtures/architecture/dependency-baseline.json b/tests/fixtures/architecture/dependency-baseline.json index aee1ed3eb..f0c000181 100644 --- a/tests/fixtures/architecture/dependency-baseline.json +++ b/tests/fixtures/architecture/dependency-baseline.json @@ -13,8 +13,8 @@ "runtime_to_db": [], "workflow_to_db": [] }, - "edge_count": 6416, - "edge_sha256": "c138400e259f15da3b22796667691ccca229c9c8b9a4c88f3c122922600c38a1", + "edge_count": 6417, + "edge_sha256": "ded73ef8389d2d3ba9328063bad2afb6bda982fa14a8a4ae6eb369ba4e3c345c", "edges": [ "app -> app.runtime", "app -> app.runtime.compat", @@ -384,8 +384,9 @@ "app.agent.prompt -> app.schemas.notification", "app.agent.prompt.transfer_redo -> app.agent", "app.agent.prompt.transfer_redo -> app.agent.prompt", + "app.agent.runtime -> app.application", + "app.agent.runtime -> app.application.configuration", "app.agent.runtime -> app.runtime", - "app.agent.runtime -> app.runtime.config", "app.agent.runtime -> app.runtime.log", "app.agent.runtime_loader -> app.agent", "app.agent.runtime_loader -> app.agent.capabilities", diff --git a/tests/test_agent_runtime.py b/tests/test_agent_runtime.py index 4b709f421..620bf9421 100644 --- a/tests/test_agent_runtime.py +++ b/tests/test_agent_runtime.py @@ -2,6 +2,8 @@ import shutil import tempfile import textwrap import unittest +from types import SimpleNamespace +from unittest.mock import patch from pathlib import Path from app.agent.runtime import AgentRuntimeManager @@ -23,6 +25,16 @@ class TestAgentRuntimeConfig(unittest.TestCase): bundled_defaults_dir=self.defaults_root, ) + def test_default_root_uses_runtime_settings_service(self): + """未显式传入目录时,管理器应读取组合根提供的配置目录。""" + config_root = self.temp_root / "configured" + service = SimpleNamespace(get=lambda key: config_root if key == "CONFIG_PATH" else None) + + with patch("app.agent.runtime.get_runtime_settings", return_value=service): + manager = AgentRuntimeManager(bundled_defaults_dir=self.defaults_root) + + self.assertEqual(manager.agent_root_dir, config_root / "agent") + def test_load_runtime_config_syncs_defaults_and_parses_sections(self): manager = self._manager()