Refactor movie pilot config and test coverage

This commit is contained in:
jxxghp
2026-06-23 10:05:45 +08:00
parent dc773337d3
commit 0cd049bfc2
40 changed files with 1481 additions and 828 deletions

View File

@@ -9,8 +9,11 @@ from app.agent.tools.base import MoviePilotTool
from app.agent.tools.tags import ToolTag
from app.agent.tools.impl._system_setting_utils import (
SettingSpec,
is_secret_setting_key,
list_setting_specs,
redact_secret_value,
resolve_setting_spec,
should_redact_setting,
)
from app.core.config import settings
from app.db.systemconfig_oper import SystemConfigOper
@@ -53,6 +56,13 @@ class QuerySystemSettingsInput(BaseModel):
"when multiple settings are matched it returns summaries only unless this is explicitly set to true."
),
)
show_secrets: Optional[bool] = Field(
False,
description=(
"Whether to return raw secret values such as API keys, tokens, cookies, and passwords. "
"Defaults to false; secret-like fields are redacted in returned values and previews."
),
)
class QuerySystemSettingsTool(MoviePilotTool):
@@ -85,15 +95,18 @@ class QuerySystemSettingsTool(MoviePilotTool):
@staticmethod
def _load_setting_value(spec: SettingSpec):
"""读取指定设置项的当前值。"""
if spec.source == "settings":
return getattr(settings, spec.key)
return SystemConfigOper().get(spec.key)
return SystemConfigOper().get(spec.systemconfig_key)
@staticmethod
def _summarize_value(value) -> dict:
def _summarize_value(value, *, redacted: bool = False) -> dict:
"""生成设置值摘要,避免列表和字典默认输出过长。"""
summary = {
"has_value": value is not None,
"value_type": type(value).__name__,
"redacted": redacted,
}
if isinstance(value, list):
summary["item_count"] = len(value)
@@ -122,14 +135,12 @@ class QuerySystemSettingsTool(MoviePilotTool):
group: Optional[str] = "all",
keyword: Optional[str] = None,
include_values: Optional[bool] = None,
show_secrets: Optional[bool] = False,
**kwargs,
) -> str:
logger.info(
"执行工具: %s, setting_key=%s, group=%s, keyword=%s",
self.name,
setting_key,
group,
keyword,
f"执行工具: {self.name}, setting_key={setting_key}, "
f"group={group}, keyword={keyword}"
)
try:
@@ -158,18 +169,30 @@ class QuerySystemSettingsTool(MoviePilotTool):
should_include_values = (
include_values if include_values is not None else len(specs) == 1
)
allow_secret_values = bool(show_secrets) and await self.is_admin_user()
settings_payload = []
for spec in specs:
value = self._load_setting_value(spec)
should_redact = (
should_redact_setting(spec, value) and not allow_secret_values
)
response_value = (
redact_secret_value(
value,
redact_scalar=is_secret_setting_key(spec.key),
)
if should_redact
else value
)
item = {
"setting_key": spec.key,
"source": spec.source,
"group": spec.group,
"label": spec.label,
}
item.update(self._summarize_value(value))
item.update(self._summarize_value(response_value, redacted=should_redact))
if should_include_values:
item["value"] = value
item["value"] = response_value
settings_payload.append(item)
return json.dumps(
@@ -177,6 +200,7 @@ class QuerySystemSettingsTool(MoviePilotTool):
"success": True,
"matched_count": len(settings_payload),
"include_values": should_include_values,
"show_secrets": allow_secret_values,
"settings": settings_payload,
},
ensure_ascii=False,