refactor(plugin_system): 废弃旧版Command系统并重构注册中心
本次提交完全移除了对旧版 `BaseCommand` 系统的支持,统一使用 `PlusCommand`。所有旧版命令现在通过一个兼容性适配器在加载时自动转换为 `PlusCommand`,简化了命令处理流程和代码库。
主要变更:
- **移除旧版命令处理**: 删除了 `ChatBot` 中专门处理旧版 `BaseCommand` 的方法 (`_process_commands_with_new_system`) 和相关逻辑,现在所有命令都通过 `PlusCommand` 的处理流程。
- **重构组件注册中心**: 对 `ComponentRegistry` 进行了大规模重构和清理:
- 添加了大量文档字符串和类型提示,显著提升了代码的可读性和可维护性。
- 废弃了特定于 `BaseCommand` 的注册表和查找方法 (`_command_registry`, `_command_patterns`, `find_command_by_text`)。
- 实现了 `unregister_plugin` 和 `remove_component` 方法,支持插件和组件在运行时的动态卸载。
- 统一并简化了各类组件的注册、查询和状态管理逻辑,使其更加一致和健壮。
BREAKING CHANGE: 废弃了 `BaseCommand` 类。所有自定义命令现在必须继承自 `PlusCommand`。虽然系统提供了向后兼容的适配器,但强烈建议将现有命令迁移到 `PlusCommand` 以获得全部功能和最佳性能。直接依赖旧版 `BaseCommand` 注册和查找机制的代码将无法工作。
This commit is contained in:
@@ -197,80 +197,6 @@ class ChatBot:
|
||||
logger.error(f"处理PlusCommand时出错: {e}")
|
||||
return False, None, True # 出错时继续处理消息
|
||||
|
||||
async def _process_commands_with_new_system(self, message: DatabaseMessages, chat: ChatStream):
|
||||
# sourcery skip: use-named-expression
|
||||
"""使用新插件系统处理命令"""
|
||||
try:
|
||||
text = message.processed_plain_text or ""
|
||||
|
||||
# 使用新的组件注册中心查找命令
|
||||
command_result = component_registry.find_command_by_text(text)
|
||||
if command_result:
|
||||
command_class, matched_groups, command_info = command_result
|
||||
plugin_name = command_info.plugin_name
|
||||
command_name = command_info.name
|
||||
if (
|
||||
chat
|
||||
and chat.stream_id
|
||||
and command_name
|
||||
in global_announcement_manager.get_disabled_chat_commands(chat.stream_id)
|
||||
):
|
||||
logger.info("用户禁用的命令,跳过处理")
|
||||
return False, None, True
|
||||
|
||||
message.is_command = True
|
||||
|
||||
# 获取插件配置
|
||||
plugin_config = component_registry.get_plugin_config(plugin_name)
|
||||
|
||||
# 创建命令实例
|
||||
command_instance: BaseCommand = command_class(message, plugin_config)
|
||||
command_instance.set_matched_groups(matched_groups)
|
||||
|
||||
# 为插件实例设置 chat_stream 运行时属性
|
||||
setattr(command_instance, "chat_stream", chat)
|
||||
|
||||
try:
|
||||
# 检查聊天类型限制
|
||||
if not command_instance.is_chat_type_allowed():
|
||||
is_group = chat.group_info is not None
|
||||
logger.info(
|
||||
f"命令 {command_class.__name__} 不支持当前聊天类型: {'群聊' if is_group else '私聊'}"
|
||||
)
|
||||
return False, None, True # 跳过此命令,继续处理其他消息
|
||||
|
||||
# 执行命令
|
||||
success, response, intercept_message = await command_instance.execute()
|
||||
|
||||
# 记录命令执行结果
|
||||
if success:
|
||||
logger.info(f"命令执行成功: {command_class.__name__} (拦截: {intercept_message})")
|
||||
else:
|
||||
logger.warning(f"命令执行失败: {command_class.__name__} - {response}")
|
||||
|
||||
# 根据命令的拦截设置决定是否继续处理消息
|
||||
return True, response, not intercept_message # 找到命令,根据intercept_message决定是否继续
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行命令时出错: {command_class.__name__} - {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
try:
|
||||
await command_instance.send_text(f"命令执行出错: {e!s}")
|
||||
except Exception as send_error:
|
||||
logger.error(f"发送错误消息失败: {send_error}")
|
||||
|
||||
# 命令出错时,根据命令的拦截设置决定是否继续处理消息
|
||||
return True, str(e), False # 出错时继续处理消息
|
||||
|
||||
# 没有找到命令,继续处理消息
|
||||
return False, None, True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理命令时出错: {e}")
|
||||
return False, None, True # 出错时继续处理消息
|
||||
|
||||
|
||||
async def _handle_adapter_response_from_dict(self, seg_data: dict | None):
|
||||
"""处理适配器命令响应(从字典数据)"""
|
||||
try:
|
||||
@@ -412,16 +338,6 @@ class ChatBot:
|
||||
logger.info(f"PlusCommand处理完成,跳过后续消息处理: {plus_cmd_result}")
|
||||
return
|
||||
|
||||
# 如果不是PlusCommand,尝试传统的BaseCommand处理
|
||||
if not is_plus_command:
|
||||
is_command, cmd_result, continue_process = await self._process_commands_with_new_system(message, chat)
|
||||
|
||||
# 如果是命令且不需要继续处理,则直接返回
|
||||
if is_command and not continue_process:
|
||||
await MessageStorage.store_message(message, chat)
|
||||
logger.info(f"命令处理完成,跳过后续消息处理: {cmd_result}")
|
||||
return
|
||||
|
||||
result = await event_manager.trigger_event(EventType.ON_MESSAGE, permission_group="SYSTEM", message=message)
|
||||
if result and not result.all_continue_process():
|
||||
raise UserWarning(f"插件{result.get_summary().get('stopped_handlers', '')}于消息到达时取消了消息处理")
|
||||
|
||||
@@ -29,14 +29,16 @@ class PromptComponentManager:
|
||||
|
||||
def __init__(self):
|
||||
"""初始化管理器实例。"""
|
||||
# _dynamic_rules 仅用于存储通过 API 动态添加的、非静态组件的规则。
|
||||
# _dynamic_rules 存储通过 API 在运行时动态添加/修改的规则。
|
||||
# 这是实现提示词动态性的核心数据结构。
|
||||
# 结构: {
|
||||
# "target_prompt_name": {
|
||||
# "prompt_component_name": (InjectionRule, content_provider, source)
|
||||
# "target_prompt_name": { // 目标 Prompt 的名称
|
||||
# "prompt_component_name": (InjectionRule, content_provider, source) // 注入组件的规则详情
|
||||
# }
|
||||
# }
|
||||
self._dynamic_rules: dict[str, dict[str, tuple[InjectionRule, Callable[..., Awaitable[str]], str]]] = {}
|
||||
self._lock = asyncio.Lock() # 锁现在保护 _dynamic_rules
|
||||
# 使用 asyncio.Lock 来确保对 _dynamic_rules 的所有写操作都是线程安全的。
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
# --- 运行时规则管理 API ---
|
||||
|
||||
@@ -64,9 +66,13 @@ class PromptComponentManager:
|
||||
Returns:
|
||||
bool: 如果成功添加或更新,则返回 True。
|
||||
"""
|
||||
# 加锁以保证多协程环境下的数据一致性
|
||||
async with self._lock:
|
||||
# 遍历所有待添加的规则
|
||||
for rule in rules:
|
||||
# 使用 setdefault 确保目标 prompt 的规则字典存在
|
||||
target_rules = self._dynamic_rules.setdefault(rule.target_prompt, {})
|
||||
# 添加或覆盖指定组件的规则、内容提供者和来源
|
||||
target_rules[prompt_name] = (rule, content_provider, source)
|
||||
logger.info(f"成功添加/更新注入规则: '{prompt_name}' -> '{rule.target_prompt}' (来源: {source})")
|
||||
return True
|
||||
@@ -88,15 +94,16 @@ class PromptComponentManager:
|
||||
如果未找到该组件的任何现有规则(无法复用),则返回 False。
|
||||
"""
|
||||
async with self._lock:
|
||||
# 步骤 1: 查找现有的 content_provider 和 source
|
||||
# 步骤 1: 遍历所有动态规则,查找指定组件已存在的 provider 和 source
|
||||
found_provider: Callable[..., Awaitable[str]] | None = None
|
||||
found_source: str | None = None
|
||||
for target_rules in self._dynamic_rules.values():
|
||||
if prompt_name in target_rules:
|
||||
# 如果找到,记录其 provider 和 source 并跳出循环
|
||||
_, found_provider, found_source = target_rules[prompt_name]
|
||||
break
|
||||
|
||||
# 步骤 2: 如果找不到 provider,则操作失败
|
||||
# 步骤 2: 如果遍历完仍未找到 provider,说明该组件无任何规则,无法复用
|
||||
if not found_provider:
|
||||
logger.warning(
|
||||
f"尝试为组件 '{prompt_name}' 添加规则失败: "
|
||||
@@ -105,7 +112,7 @@ class PromptComponentManager:
|
||||
return False
|
||||
|
||||
# 步骤 3: 使用找到的 provider 和 source 添加新规则
|
||||
source_to_use = found_source or "runtime" # 提供一个默认值以防万一
|
||||
source_to_use = found_source or "runtime" # 如果 source 为 None,提供默认值
|
||||
target_rules = self._dynamic_rules.setdefault(rule.target_prompt, {})
|
||||
target_rules[prompt_name] = (rule, found_provider, source_to_use)
|
||||
logger.info(
|
||||
@@ -126,13 +133,16 @@ class PromptComponentManager:
|
||||
bool: 如果成功移除,则返回 True;如果规则不存在,则返回 False。
|
||||
"""
|
||||
async with self._lock:
|
||||
# 检查目标和组件规则是否存在
|
||||
if target_prompt in self._dynamic_rules and prompt_name in self._dynamic_rules[target_prompt]:
|
||||
# 存在则删除
|
||||
del self._dynamic_rules[target_prompt][prompt_name]
|
||||
# 如果目标下已无任何规则,则清理掉这个键
|
||||
# 如果删除后,该目标下已无任何规则,则清理掉这个目标键,保持数据结构整洁
|
||||
if not self._dynamic_rules[target_prompt]:
|
||||
del self._dynamic_rules[target_prompt]
|
||||
logger.info(f"成功移除注入规则: '{prompt_name}' from '{target_prompt}'")
|
||||
return True
|
||||
# 如果规则不存在,记录警告并返回 False
|
||||
logger.warning(f"尝试移除注入规则失败: 未找到 '{prompt_name}' on '{target_prompt}'")
|
||||
return False
|
||||
|
||||
@@ -153,7 +163,9 @@ class PromptComponentManager:
|
||||
async with self._lock:
|
||||
# 创建一个目标列表的副本进行迭代,因为我们可能会在循环中修改字典
|
||||
for target_prompt in list(self._dynamic_rules.keys()):
|
||||
# 检查当前目标下是否存在该组件的规则
|
||||
if prompt_name in self._dynamic_rules[target_prompt]:
|
||||
# 存在则删除
|
||||
del self._dynamic_rules[target_prompt][prompt_name]
|
||||
removed = True
|
||||
logger.info(f"成功移除注入规则: '{prompt_name}' from '{target_prompt}'")
|
||||
@@ -176,17 +188,23 @@ class PromptComponentManager:
|
||||
async def content_provider(params: PromptParameters, target_prompt_name: str) -> str:
|
||||
"""实际执行内容生成的异步函数。"""
|
||||
try:
|
||||
# 从注册表获取组件信息,用于后续获取插件配置
|
||||
p_info = component_registry.get_component_info(component_name, ComponentType.PROMPT)
|
||||
plugin_config = {}
|
||||
if isinstance(p_info, PromptInfo):
|
||||
# 获取该组件所属插件的配置
|
||||
plugin_config = component_registry.get_plugin_config(p_info.plugin_name)
|
||||
|
||||
# 实例化组件,并传入所需参数
|
||||
instance = component_class(
|
||||
params=params, plugin_config=plugin_config, target_prompt_name=target_prompt_name
|
||||
)
|
||||
# 执行组件的 execute 方法以生成内容
|
||||
result = await instance.execute()
|
||||
# 确保返回的是字符串
|
||||
return str(result) if result is not None else ""
|
||||
except Exception as e:
|
||||
# 捕获并记录执行过程中的任何异常,返回空字符串以避免注入失败
|
||||
logger.error(f"执行规则提供者 '{component_name}' 时出错: {e}", exc_info=True)
|
||||
return ""
|
||||
|
||||
@@ -202,16 +220,20 @@ class PromptComponentManager:
|
||||
if not isinstance(info, PromptInfo):
|
||||
continue
|
||||
|
||||
# 实时检查组件是否启用
|
||||
# 实时检查组件是否已启用,跳过禁用的组件
|
||||
if not component_registry.is_component_available(name, ComponentType.PROMPT):
|
||||
continue
|
||||
|
||||
# 获取组件的类定义
|
||||
component_class = component_registry.get_component_class(name, ComponentType.PROMPT)
|
||||
if not (component_class and issubclass(component_class, BasePrompt)):
|
||||
continue
|
||||
|
||||
# 为该组件创建一个内容提供者
|
||||
provider = self._create_content_provider(name, component_class)
|
||||
# 遍历组件定义的所有注入规则
|
||||
for rule in info.injection_rules:
|
||||
# 如果规则的目标与当前目标匹配,则添加到列表中
|
||||
if rule.target_prompt == target_prompt_name:
|
||||
all_rules.append((rule, provider, "static"))
|
||||
|
||||
@@ -219,11 +241,13 @@ class PromptComponentManager:
|
||||
async with self._lock:
|
||||
runtime_rules = self._dynamic_rules.get(target_prompt_name, {})
|
||||
for name, (rule, provider, source) in runtime_rules.items():
|
||||
# 确保运行时组件不会与禁用的静态组件冲突
|
||||
# 检查该运行时规则是否关联到一个已注册的静态组件
|
||||
static_info = component_registry.get_component_info(name, ComponentType.PROMPT)
|
||||
# 如果关联的静态组件存在且被禁用,则跳过此运行时规则
|
||||
if static_info and not component_registry.is_component_available(name, ComponentType.PROMPT):
|
||||
logger.debug(f"跳过运行时规则 '{name}',因为它关联的静态组件当前已禁用。")
|
||||
continue
|
||||
# 将有效的运行时规则添加到列表
|
||||
all_rules.append((rule, provider, source))
|
||||
|
||||
return all_rules
|
||||
@@ -252,17 +276,19 @@ class PromptComponentManager:
|
||||
Returns:
|
||||
str: 应用了所有注入规则后,最终生成的提示词模板字符串。
|
||||
"""
|
||||
# 构建适用于当前目标的所有规则
|
||||
rules_for_target = await self._build_rules_for_target(target_prompt_name)
|
||||
if not rules_for_target:
|
||||
# 如果没有规则,直接返回原始模板
|
||||
return original_template
|
||||
|
||||
# --- 占位符保护机制 ---
|
||||
# 1. 保护: 找到所有 {placeholder} 并用临时标记替换
|
||||
placeholders = re.findall(r"({[^{}]+})", original_template)
|
||||
placeholder_map: dict[str, str] = {
|
||||
f"__PROMPT_PLACEHOLDER_{i}__": p for i, p in enumerate(placeholders)
|
||||
}
|
||||
|
||||
# 1. 保护: 将占位符替换为临时标记
|
||||
protected_template = original_template
|
||||
for marker, placeholder in placeholder_map.items():
|
||||
protected_template = protected_template.replace(placeholder, marker)
|
||||
@@ -271,6 +297,7 @@ class PromptComponentManager:
|
||||
for rule, _, source in rules_for_target:
|
||||
if rule.injection_type in (InjectionType.REMOVE, InjectionType.REPLACE) and rule.target_content:
|
||||
try:
|
||||
# 检查规则的 target_content (正则) 是否可能匹配到任何一个占位符
|
||||
for p in placeholders:
|
||||
if re.search(rule.target_content, p):
|
||||
logger.warning(
|
||||
@@ -278,10 +305,10 @@ class PromptComponentManager:
|
||||
f"规则 `target_content` ('{rule.target_content}') "
|
||||
f"可能会影响核心占位符 '{p}'。为保证系统稳定,该占位符已被保护,不会被此规则修改。"
|
||||
)
|
||||
# 只对每个规则警告一次
|
||||
# 每个规则只警告一次
|
||||
break
|
||||
except re.error:
|
||||
# 正则表达式本身有误,后面执行时会再次捕获,这里可忽略
|
||||
# 如果正则表达式本身有误,后续执行时会捕获,此处可忽略
|
||||
pass
|
||||
|
||||
# 3. 安全执行: 按优先级排序并应用规则
|
||||
@@ -290,13 +317,16 @@ class PromptComponentManager:
|
||||
modified_template = protected_template
|
||||
for rule, provider, source in rules_for_target:
|
||||
content = ""
|
||||
# REMOVE 类型不需要生成内容
|
||||
if rule.injection_type != InjectionType.REMOVE:
|
||||
try:
|
||||
# 调用内容提供者生成要注入的文本
|
||||
content = await provider(params, target_prompt_name)
|
||||
except Exception as e:
|
||||
logger.error(f"执行规则 '{rule}' (来源: {source}) 的内容提供者时失败: {e}", exc_info=True)
|
||||
continue
|
||||
continue # 执行失败则跳过此规则
|
||||
|
||||
# 应用注入规则
|
||||
try:
|
||||
if rule.injection_type == InjectionType.PREPEND:
|
||||
if content:
|
||||
@@ -309,6 +339,7 @@ class PromptComponentManager:
|
||||
modified_template = re.sub(rule.target_content, str(content), modified_template)
|
||||
elif rule.injection_type == InjectionType.INSERT_AFTER:
|
||||
if content and rule.target_content:
|
||||
# 使用 \\g<0> 在匹配项后插入内容
|
||||
replacement = f"\\g<0>\n{content}"
|
||||
modified_template = re.sub(rule.target_content, replacement, modified_template)
|
||||
elif rule.injection_type == InjectionType.REMOVE:
|
||||
@@ -319,7 +350,7 @@ class PromptComponentManager:
|
||||
except Exception as e:
|
||||
logger.error(f"应用注入规则 '{rule}' (来源: {source}) 失败: {e}", exc_info=True)
|
||||
|
||||
# 4. 占位符恢复
|
||||
# 4. 占位符恢复: 将临时标记替换回原始的占位符
|
||||
final_template = modified_template
|
||||
for marker, placeholder in placeholder_map.items():
|
||||
final_template = final_template.replace(marker, placeholder)
|
||||
@@ -343,8 +374,9 @@ class PromptComponentManager:
|
||||
str: 模拟生成的最终提示词模板字符串。如果找不到模板,则返回错误信息。
|
||||
"""
|
||||
try:
|
||||
# 从全局提示词管理器获取最原始的模板内容
|
||||
# 动态导入以避免循环依赖
|
||||
from src.chat.utils.prompt import global_prompt_manager
|
||||
# 从全局管理器获取原始的、未经修改的提示词对象
|
||||
original_prompt = global_prompt_manager._prompts.get(target_prompt_name)
|
||||
if not original_prompt:
|
||||
logger.warning(f"无法预览 '{target_prompt_name}',因为找不到这个核心 Prompt。")
|
||||
@@ -354,14 +386,16 @@ class PromptComponentManager:
|
||||
logger.warning(f"无法预览 '{target_prompt_name}',因为找不到这个核心 Prompt。")
|
||||
return f"Error: Prompt '{target_prompt_name}' not found."
|
||||
|
||||
# 直接调用核心注入逻辑来模拟结果
|
||||
# 直接调用核心注入逻辑来模拟并返回结果
|
||||
return await self.apply_injections(target_prompt_name, original_template, params)
|
||||
|
||||
# --- 状态观测与查询 API ---
|
||||
|
||||
def get_core_prompts(self) -> list[str]:
|
||||
"""获取所有已注册的核心提示词模板名称列表(即所有可注入的目标)。"""
|
||||
# 动态导入以避免循环依赖
|
||||
from src.chat.utils.prompt import global_prompt_manager
|
||||
# 返回所有核心 prompt 的名称列表
|
||||
return list(global_prompt_manager._prompts.keys())
|
||||
|
||||
def get_core_prompt_contents(self, prompt_name: str | None = None) -> list[list[str]]:
|
||||
@@ -381,9 +415,11 @@ class PromptComponentManager:
|
||||
from src.chat.utils.prompt import global_prompt_manager
|
||||
|
||||
if prompt_name:
|
||||
# 如果指定了名称,则查找并返回单个模板
|
||||
prompt = global_prompt_manager._prompts.get(prompt_name)
|
||||
return [[prompt_name, prompt.template]] if prompt else []
|
||||
|
||||
# 如果未指定名称,则返回所有模板的列表
|
||||
return [[name, prompt.template] for name, prompt in global_prompt_manager._prompts.items()]
|
||||
|
||||
async def get_registered_prompt_component_info(self) -> list[PromptInfo]:
|
||||
@@ -391,21 +427,23 @@ class PromptComponentManager:
|
||||
获取所有已注册和动态添加的Prompt组件信息,并反映当前的注入规则状态。
|
||||
此方法现在直接从 component_registry 获取静态组件信息,并合并纯运行时的组件信息。
|
||||
"""
|
||||
# 该方法现在直接从 component_registry 获取信息,因为它总是有最新的数据
|
||||
# 从注册表获取所有已注册的静态 Prompt 组件信息
|
||||
all_components = component_registry.get_components_by_type(ComponentType.PROMPT)
|
||||
info_list = [info for info in all_components.values() if isinstance(info, PromptInfo)]
|
||||
|
||||
# 检查是否有纯动态组件需要添加
|
||||
# 检查并合并仅在运行时通过 API 添加的“纯动态”组件
|
||||
async with self._lock:
|
||||
runtime_component_names = set()
|
||||
# 收集所有动态规则中涉及的组件名称
|
||||
for rules in self._dynamic_rules.values():
|
||||
runtime_component_names.update(rules.keys())
|
||||
|
||||
static_component_names = {info.name for info in info_list}
|
||||
# 找出那些只存在于动态规则中,但未在静态组件中注册的名称
|
||||
pure_dynamic_names = runtime_component_names - static_component_names
|
||||
|
||||
for name in pure_dynamic_names:
|
||||
# 为纯动态组件创建临时的 PromptInfo
|
||||
# 为这些“纯动态”组件创建一个临时的信息对象
|
||||
dynamic_info = PromptInfo(
|
||||
name=name,
|
||||
component_type=ComponentType.PROMPT,
|
||||
@@ -413,7 +451,7 @@ class PromptComponentManager:
|
||||
plugin_name="runtime",
|
||||
is_built_in=False,
|
||||
)
|
||||
# 从 _dynamic_rules 中收集其所有规则
|
||||
# 从动态规则中收集并关联其所有注入规则
|
||||
for target, rules_in_target in self._dynamic_rules.items():
|
||||
if name in rules_in_target:
|
||||
rule, _, _ = rules_in_target[name]
|
||||
@@ -433,10 +471,11 @@ class PromptComponentManager:
|
||||
"""
|
||||
info_map = {}
|
||||
all_core_prompts = self.get_core_prompts()
|
||||
# 确定要处理的目标:如果指定了有效的目标,则只处理它;否则处理所有核心 prompt
|
||||
targets_to_process = [target_prompt] if target_prompt and target_prompt in all_core_prompts else all_core_prompts
|
||||
|
||||
for target in targets_to_process:
|
||||
# 动态构建规则列表
|
||||
# 动态构建该目标的所有有效规则
|
||||
rules_for_target = await self._build_rules_for_target(target)
|
||||
if not rules_for_target:
|
||||
info_map[target] = []
|
||||
@@ -444,9 +483,10 @@ class PromptComponentManager:
|
||||
|
||||
info_list = []
|
||||
for rule, _, source in rules_for_target:
|
||||
# 从规则本身获取组件名
|
||||
# 从规则对象中获取其所属组件的名称
|
||||
prompt_name = rule.owner_component
|
||||
if detailed:
|
||||
# 如果需要详细信息,则添加更多字段
|
||||
info_list.append(
|
||||
{
|
||||
"name": prompt_name,
|
||||
@@ -457,8 +497,10 @@ class PromptComponentManager:
|
||||
}
|
||||
)
|
||||
else:
|
||||
# 否则只添加基本信息
|
||||
info_list.append({"name": prompt_name, "priority": rule.priority, "source": source})
|
||||
|
||||
# 按优先级对结果进行排序
|
||||
info_list.sort(key=lambda x: x["priority"])
|
||||
info_map[target] = info_list
|
||||
return info_map
|
||||
@@ -491,31 +533,33 @@ class PromptComponentManager:
|
||||
for name, info in static_components.items():
|
||||
if not isinstance(info, PromptInfo):
|
||||
continue
|
||||
# 应用 component_name 筛选
|
||||
# 如果指定了 component_name 且不匹配,则跳过此组件
|
||||
if component_name and name != component_name:
|
||||
continue
|
||||
|
||||
for rule in info.injection_rules:
|
||||
# 应用 target_prompt 筛选
|
||||
# 如果指定了 target_prompt 且不匹配,则跳过此规则
|
||||
if target_prompt and rule.target_prompt != target_prompt:
|
||||
continue
|
||||
target_dict = all_rules.setdefault(rule.target_prompt, {})
|
||||
target_dict[name] = rule
|
||||
|
||||
# 2. 收集并合并所有纯运行时规则
|
||||
# 2. 收集并合并所有运行时规则
|
||||
async with self._lock:
|
||||
for target, rules_in_target in self._dynamic_rules.items():
|
||||
# 应用 target_prompt 筛选
|
||||
# 如果指定了 target_prompt 且不匹配,则跳过此目标下的所有规则
|
||||
if target_prompt and target != target_prompt:
|
||||
continue
|
||||
|
||||
for name, (rule, _, _) in rules_in_target.items():
|
||||
# 应用 component_name 筛选
|
||||
# 如果指定了 component_name 且不匹配,则跳过此规则
|
||||
if component_name and name != component_name:
|
||||
continue
|
||||
target_dict = all_rules.setdefault(target, {})
|
||||
# 运行时规则会覆盖同名的静态规则
|
||||
target_dict[name] = rule
|
||||
|
||||
# 返回深拷贝以防止外部修改影响内部状态
|
||||
return copy.deepcopy(all_rules)
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user