From ce2d1acc7c2b0b36f87de9ec0e1b4fb3c8ddd3e3 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Thu, 13 Nov 2025 17:17:48 +0800 Subject: [PATCH 1/6] =?UTF-8?q?refactor(prompt):=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=92=8C=E7=BB=9F=E4=B8=80=E6=8F=90=E7=A4=BA=E8=AF=8D=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E6=9F=A5=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将多个功能重叠的查询方法整合为两个核心方法,以提供更清晰、更灵活的 API,方便获取注入信息和规则。 - `get_injection_info` 方法取代了原有的 `get_full_injection_map` 和 `get_injections_for_prompt`。它现在支持按目标提示词进行筛选,并能通过 `detailed` 参数控制返回信息的详细程度。 - `get_injection_rules` 方法整合了 `get_all_dynamic_rules`、`get_rules_for_target` 和 `get_rules_by_component` 的功能。现在可以通过一个方法,灵活地按目标、按组件或按两者的组合来筛选注入规则。 - 已更新 `system_management` 插件中的相关命令以适配新的 API。 BREAKING CHANGE: `PromptComponentManager` 的公共 API 已更改。 移除了 `get_full_injection_map`, `get_injections_for_prompt`, `get_all_dynamic_rules`, `get_rules_for_target`, `get_rules_by_component` 方法。 请分别使用新的 `get_injection_info` 和 `get_injection_rules` 方法进行替代。 --- src/chat/utils/prompt_component_manager.py | 163 +++++++++--------- .../built_in/system_management/plugin.py | 8 +- 2 files changed, 90 insertions(+), 81 deletions(-) diff --git a/src/chat/utils/prompt_component_manager.py b/src/chat/utils/prompt_component_manager.py index 610bbe0c2..8b8d0e3ba 100644 --- a/src/chat/utils/prompt_component_manager.py +++ b/src/chat/utils/prompt_component_manager.py @@ -287,110 +287,117 @@ class PromptComponentManager: components = component_registry.get_components_by_type(ComponentType.PROMPT).values() return [info for info in components if isinstance(info, PromptInfo)] - async def get_full_injection_map(self) -> dict[str, list[dict]]: + async def get_injection_info( + self, + target_prompt: str | None = None, + detailed: bool = False, + ) -> dict[str, list[dict]]: """ - 获取当前完整的注入映射图。 + 获取注入信息的映射图,可按目标筛选,并可控制信息的详细程度。 - 此方法提供了一个系统全局的注入视图,展示了每个核心提示词(target) - 被哪些注入组件(source)以何种优先级注入。 + - `get_injection_info()` 返回所有目标的摘要注入信息。 + - `get_injection_info(target_prompt="...")` 返回指定目标的摘要注入信息。 + - `get_injection_info(detailed=True)` 返回所有目标的详细注入信息。 + - `get_injection_info(target_prompt="...", detailed=True)` 返回指定目标的详细注入信息。 + + Args: + target_prompt (str, optional): 如果指定,仅返回该目标的注入信息。 + detailed (bool, optional): 如果为 True,则返回包含注入类型和内容的详细信息。 + 默认为 False,返回摘要信息。 Returns: dict[str, list[dict]]: 一个字典,键是目标提示词名称, - 值是按优先级排序的注入信息列表。 - `[{"name": str, "priority": int, "source": str}]` + 值是按优先级排序的注入信息列表。 """ - injection_map = {} + info_map = {} async with self._lock: - # 合并所有动态规则的目标和所有核心提示词,确保所有潜在目标都被包含 all_targets = set(self._dynamic_rules.keys()) | set(self.get_core_prompts()) - for target in sorted(all_targets): + + # 如果指定了目标,则只处理该目标 + targets_to_process = [target_prompt] if target_prompt and target_prompt in all_targets else sorted(all_targets) + + for target in targets_to_process: rules = self._dynamic_rules.get(target, {}) if not rules: - injection_map[target] = [] + info_map[target] = [] continue info_list = [] for prompt_name, (rule, _, source) in rules.items(): - info_list.append({"name": prompt_name, "priority": rule.priority, "source": source}) + if detailed: + info_list.append( + { + "name": prompt_name, + "priority": rule.priority, + "source": source, + "injection_type": rule.injection_type.value, + "target_content": rule.target_content, + } + ) + else: + info_list.append({"name": prompt_name, "priority": rule.priority, "source": source}) - # 按优先级排序后存入 map info_list.sort(key=lambda x: x["priority"]) - injection_map[target] = info_list - return injection_map + info_map[target] = info_list + return info_map - async def get_injections_for_prompt(self, target_prompt_name: str) -> list[dict]: + def get_injection_rules( + self, + target_prompt: str | None = None, + component_name: str | None = None, + ) -> dict[str, dict[str, "InjectionRule"]]: """ - 获取指定核心提示词模板的所有注入信息(包含详细规则)。 + 获取动态注入规则,可通过目标或组件名称进行筛选。 + + - 不提供任何参数时,返回所有规则。 + - 提供 `target_prompt` 时,仅返回注入到该目标的规则。 + - 提供 `component_name` 时,仅返回由该组件定义的所有规则。 + - 同时提供 `target_prompt` 和 `component_name` 时,返回满足两个条件的规则。 Args: - target_prompt_name (str): 目标核心提示词的名称。 + target_prompt (str, optional): 按目标核心提示词名称筛选。 + component_name (str, optional): 按注入组件名称筛选。 Returns: - list[dict]: 一个包含注入规则详细信息的列表,已按优先级排序。 - """ - rules_for_target = self._dynamic_rules.get(target_prompt_name, {}) - if not rules_for_target: - return [] - - info_list = [] - for prompt_name, (rule, _, source) in rules_for_target.items(): - info_list.append( - { - "name": prompt_name, - "priority": rule.priority, - "source": source, - "injection_type": rule.injection_type.value, - "target_content": rule.target_content, - } - ) - info_list.sort(key=lambda x: x["priority"]) - return info_list - - def get_all_dynamic_rules(self) -> dict[str, dict[str, "InjectionRule"]]: - """ - 获取所有当前的动态注入规则,以 InjectionRule 对象形式返回。 - - 此方法返回一个深拷贝的规则副本,隐藏了 `content_provider` 等内部实现细节。 - 适合用于展示或序列化当前的规则配置。 + dict[str, dict[str, InjectionRule]]: 一个深拷贝的规则字典。 + 结构: { "target_prompt": { "component_name": InjectionRule } } """ rules_copy = {} - for target, rules in self._dynamic_rules.items(): - target_copy = {name: rule for name, (rule, _, _) in rules.items()} - rules_copy[target] = target_copy + # 筛选目标 + targets_to_check = [target_prompt] if target_prompt else self._dynamic_rules.keys() + + for target in targets_to_check: + if target not in self._dynamic_rules: + continue + + rules_for_target = self._dynamic_rules[target] + target_copy = {} + + # 筛选组件 + if component_name: + if component_name in rules_for_target: + rule, _, _ = rules_for_target[component_name] + target_copy[component_name] = rule + else: + for name, (rule, _, _) in rules_for_target.items(): + target_copy[name] = rule + + if target_copy: + rules_copy[target] = target_copy + + # 如果是按组件筛选且未指定目标,则需遍历所有目标 + if component_name and not target_prompt: + found_rules = {} + for target, rules in self._dynamic_rules.items(): + if component_name in rules: + rule, _, _ = rules[component_name] + if target not in found_rules: + found_rules[target] = {} + found_rules[target][component_name] = rule + return copy.deepcopy(found_rules) + return copy.deepcopy(rules_copy) - def get_rules_for_target(self, target_prompt: str) -> dict[str, InjectionRule]: - """ - 获取所有注入到指定核心提示词的动态规则。 - - Args: - target_prompt (str): 目标核心提示词的名称。 - - Returns: - dict[str, InjectionRule]: 一个字典,键是注入组件的名称,值是 `InjectionRule` 对象。 - 如果找不到任何注入到该目标的规则,则返回一个空字典。 - """ - target_rules = self._dynamic_rules.get(target_prompt, {}) - return {name: copy.deepcopy(rule_info[0]) for name, rule_info in target_rules.items()} - - def get_rules_by_component(self, component_name: str) -> dict[str, InjectionRule]: - """ - 获取由指定的单个注入组件定义的所有动态规则。 - - Args: - component_name (str): 注入组件的名称。 - - Returns: - dict[str, InjectionRule]: 一个字典,键是目标核心提示词的名称,值是 `InjectionRule` 对象。 - 如果该组件没有定义任何注入规则,则返回一个空字典。 - """ - found_rules = {} - for target, rules in self._dynamic_rules.items(): - if component_name in rules: - rule_info = rules[component_name] - found_rules[target] = copy.deepcopy(rule_info[0]) - return found_rules - # 创建全局单例 (Singleton) # 在整个应用程序中,应该只使用这一个 `prompt_component_manager` 实例, diff --git a/src/plugins/built_in/system_management/plugin.py b/src/plugins/built_in/system_management/plugin.py index 4951a24cf..e3c7ddeb6 100644 --- a/src/plugins/built_in/system_management/plugin.py +++ b/src/plugins/built_in/system_management/plugin.py @@ -6,6 +6,7 @@ import re from typing import ClassVar + from src.chat.utils.prompt_component_manager import prompt_component_manager from src.plugin_system.apis import ( plugin_manage_api, @@ -13,6 +14,7 @@ from src.plugin_system.apis import ( from src.plugin_system.apis.logging_api import get_logger from src.plugin_system.apis.permission_api import permission_api from src.plugin_system.apis.plugin_register_api import register_plugin +from src.plugin_system.apis.unified_scheduler import TriggerType, unified_scheduler from src.plugin_system.base.base_plugin import BasePlugin from src.plugin_system.base.command_args import CommandArgs from src.plugin_system.base.component_types import ( @@ -23,7 +25,6 @@ from src.plugin_system.base.component_types import ( from src.plugin_system.base.config_types import ConfigField from src.plugin_system.base.plus_command import PlusCommand from src.plugin_system.utils.permission_decorators import require_permission -from src.plugin_system.apis.unified_scheduler import TriggerType, unified_scheduler logger = get_logger("SystemManagement") @@ -266,7 +267,7 @@ class SystemCommand(PlusCommand): @require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限") async def _show_injection_map(self): """显示全局注入关系图""" - injection_map = await prompt_component_manager.get_full_injection_map() + injection_map = await prompt_component_manager.get_injection_info() if not injection_map: await self.send_text("📊 当前没有任何提示词注入关系") return @@ -312,7 +313,8 @@ class SystemCommand(PlusCommand): @require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限") async def _get_prompt_injection_info(self, target_name: str): """获取特定核心提示词的注入详情""" - injections = await prompt_component_manager.get_injections_for_prompt(target_name) + injection_info = await prompt_component_manager.get_injection_info(target_prompt=target_name, detailed=True) + injections = injection_info.get(target_name, []) core_prompts = prompt_component_manager.get_core_prompts() if target_name not in core_prompts: From 84013783ca5fc5ac1334c6e2f1897e928da77c84 Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Thu, 13 Nov 2025 17:26:45 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat(visualizer):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=AF=E6=B8=B2=E6=9F=93=E8=8A=82=E7=82=B9=E5=92=8C=E8=BE=B9?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E5=A4=A7=E9=99=90=E5=88=B6=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E9=AB=98=E5=9B=BE=E5=BD=A2=E5=A4=84=E7=90=86=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/templates/visualizer.html | 4 ++-- src/memory_graph/utils/memory_formatter.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/templates/visualizer.html b/src/api/templates/visualizer.html index c21c5ffca..0f1f29838 100644 --- a/src/api/templates/visualizer.html +++ b/src/api/templates/visualizer.html @@ -1028,8 +1028,8 @@ console.log(`准备更新图形: ${nodeCount} 个节点, ${edgeCount} 条边`); // 对于超大数据集,进一步限制 - const MAX_RENDERABLE_NODES = 5000; - const MAX_RENDERABLE_EDGES = 10000; + const MAX_RENDERABLE_NODES = 10000; + const MAX_RENDERABLE_EDGES = 20000; let nodesToRender = data.nodes; let edgesToRender = data.edges; diff --git a/src/memory_graph/utils/memory_formatter.py b/src/memory_graph/utils/memory_formatter.py index fac7d45a2..7731ca256 100644 --- a/src/memory_graph/utils/memory_formatter.py +++ b/src/memory_graph/utils/memory_formatter.py @@ -84,12 +84,12 @@ def format_memory_for_prompt(memory: Memory, include_metadata: bool = False) -> if object_node is not None: # 有完整的主谓宾 if core_relation: - parts.append(f"{subject_text}{topic_text}{core_relation}{object_node.content}") + parts.append(f"{subject_text}-{topic_text}{core_relation}{object_node.content}") else: - parts.append(f"{subject_text}{topic_text}{object_node.content}") + parts.append(f"{subject_text}-{topic_text}{object_node.content}") else: # 只有主谓 - parts.append(f"{subject_text}{topic_text}") + parts.append(f"{subject_text}-{topic_text}") # 添加属性信息 if attributes: From 69f132a12e91d6a598f7babbb11804973f7a01c1 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Thu, 13 Nov 2025 18:18:15 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat(prompt):=20=E4=B8=BA=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=8D=E7=BB=84=E4=BB=B6=E6=8F=90=E4=BE=9B=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E7=9B=AE=E6=A0=87=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为了让单个提示词组件在注入到不同目标时能够有不同的行为,现在向组件的执行上下文中传递当前注入的目标提示词名称 (`target_prompt_name`)。 这使得组件可以根据注入点动态调整其生成的内容。例如,一个工具列表组件在注入到 planner prompt 和 reflection prompt 时可以提供不同详尽程度的列表。 主要变更: - `BasePrompt` 初始化时接收 `target_prompt_name`。 - `PromptComponentManager` 在应用注入规则时会传递此参数。 - `add_injection_rule` 方法现在支持批量添加规则,以简化注册流程。 BREAKING CHANGE: `PromptComponentManager.add_injection_rule` 中 `content_provider` 的函数签名已更改,现在需要接受第二个参数 `target_prompt_name: str`。 旧签名: `async def provider(params: PromptParameters) -> str` 新签名: `async def provider(params: PromptParameters, target_prompt_name: str) -> str --- plugins/hello_world_plugin/plugin.py | 3 ++- src/chat/utils/prompt_component_manager.py | 30 ++++++++++++---------- src/plugin_system/base/base_prompt.py | 6 +++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/plugins/hello_world_plugin/plugin.py b/plugins/hello_world_plugin/plugin.py index 078e2d367..b6242d4f6 100644 --- a/plugins/hello_world_plugin/plugin.py +++ b/plugins/hello_world_plugin/plugin.py @@ -194,6 +194,7 @@ class WeatherPrompt(BasePrompt): async def execute(self) -> str: # 在实际应用中,这里可以调用天气API # 为了演示,我们返回一个固定的天气信息 + logger.info(self.target_prompt_name) return "当前天气:晴朗,温度25°C。" @@ -202,7 +203,7 @@ class HelloWorldPlugin(BasePlugin): """一个包含四大核心组件和高级配置功能的入门示例插件。""" plugin_name = "hello_world_plugin" - enable_plugin = False + enable_plugin = True dependencies: ClassVar = [] python_dependencies: ClassVar = [] config_file_name = "config.toml" diff --git a/src/chat/utils/prompt_component_manager.py b/src/chat/utils/prompt_component_manager.py index 8b8d0e3ba..de6d0689c 100644 --- a/src/chat/utils/prompt_component_manager.py +++ b/src/chat/utils/prompt_component_manager.py @@ -2,6 +2,7 @@ import asyncio import copy import re from collections.abc import Awaitable, Callable +from typing import List from src.chat.utils.prompt_params import PromptParameters from src.common.logger import get_logger @@ -68,7 +69,9 @@ class PromptComponentManager: logger.warning(f"无法为 '{prompt_name}' 加载静态规则,因为它不是一个有效的 Prompt 组件。") continue - def create_provider(cls: type[BasePrompt]) -> Callable[[PromptParameters], Awaitable[str]]: + def create_provider( + cls: type[BasePrompt], + ) -> Callable[[PromptParameters, str], Awaitable[str]]: """ 为静态组件创建一个内容提供者闭包 (Content Provider Closure)。 @@ -80,10 +83,10 @@ class PromptComponentManager: cls (type[BasePrompt]): 需要为其创建提供者的 Prompt 组件类。 Returns: - Callable[[PromptParameters], Awaitable[str]]: 一个符合管理器标准的异步内容提供者。 + Callable[[PromptParameters, str], Awaitable[str]]: 一个符合管理器标准的异步内容提供者。 """ - async def content_provider(params: PromptParameters) -> str: + async def content_provider(params: PromptParameters, target_prompt_name: str) -> str: """实际执行内容生成的异步函数。""" try: # 从注册表获取最新的组件信息,包括插件配置 @@ -92,8 +95,8 @@ class PromptComponentManager: if isinstance(p_info, PromptInfo): plugin_config = component_registry.get_plugin_config(p_info.plugin_name) - # 实例化组件并执行 - instance = cls(params=params, plugin_config=plugin_config) + # 实例化组件并执行,传入 target_prompt_name + instance = cls(params=params, plugin_config=plugin_config, target_prompt_name=target_prompt_name) result = await instance.execute() return str(result) if result is not None else "" except Exception as e: @@ -116,31 +119,32 @@ class PromptComponentManager: async def add_injection_rule( self, prompt_name: str, - rule: InjectionRule, + rules: List[InjectionRule], content_provider: Callable[..., Awaitable[str]], source: str = "runtime", ) -> bool: """ - 动态添加或更新一条注入规则。 + 动态添加或更新注入规则。 此方法允许在系统运行时,由外部逻辑(如插件、命令)向管理器中添加新的注入行为。 如果已存在同名组件针对同一目标的规则,此方法会覆盖旧规则。 Args: prompt_name (str): 动态注入组件的唯一名称。 - rule (InjectionRule): 描述注入行为的规则对象。 + rules (List[InjectionRule]): 描述注入行为的规则对象列表。 content_provider (Callable[..., Awaitable[str]]): 一个异步函数,用于在应用注入时动态生成内容。 - 函数签名应为: `async def provider(params: "PromptParameters") -> str` + 函数签名应为: `async def provider(params: "PromptParameters", target_prompt_name: str) -> str` source (str, optional): 规则的来源标识,默认为 "runtime"。 Returns: bool: 如果成功添加或更新,则返回 True。 """ async with self._lock: - 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})") + for rule in rules: + 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 async def remove_injection_rule(self, prompt_name: str, target_prompt: str) -> bool: @@ -207,7 +211,7 @@ class PromptComponentManager: # 对于非 REMOVE 类型的注入,需要先获取内容 if rule.injection_type != InjectionType.REMOVE: try: - content = await provider(params) + content = await provider(params, target_prompt_name) except Exception as e: logger.error(f"执行规则 '{rule}' (来源: {source}) 的内容提供者时失败: {e}", exc_info=True) continue # 跳过失败的 provider,不中断整个流程 diff --git a/src/plugin_system/base/base_prompt.py b/src/plugin_system/base/base_prompt.py index 56e25c7a7..117e0b91f 100644 --- a/src/plugin_system/base/base_prompt.py +++ b/src/plugin_system/base/base_prompt.py @@ -27,22 +27,24 @@ class BasePrompt(ABC): # 定义此组件希望如何注入到核心Prompt中 # 这是一个 InjectionRule 对象的列表,可以实现复杂的注入逻辑 # 例如: [InjectionRule(target_prompt="planner_prompt", injection_type=InjectionType.APPEND, priority=50)] - injection_rules: ClassVar[list[InjectionRule] ] = [] + injection_rules: ClassVar[list[InjectionRule]] = [] """定义注入规则的列表""" # 旧的注入点定义,用于向后兼容。如果定义了这个,它将被自动转换为 injection_rules。 injection_point: str | list[str] | None = None """[已废弃] 要注入的目标Prompt名称或列表,请使用 injection_rules""" - def __init__(self, params: PromptParameters, plugin_config: dict | None = None): + def __init__(self, params: PromptParameters, plugin_config: dict | None = None, target_prompt_name: str | None = None): """初始化Prompt组件 Args: params: 统一提示词参数,包含所有构建提示词所需的上下文信息。 plugin_config: 插件配置字典。 + target_prompt_name: 在应用注入时,当前注入的目标提示词名称。 """ self.params = params self.plugin_config = plugin_config or {} + self.target_prompt_name = target_prompt_name self.log_prefix = "[PromptComponent]" logger.debug(f"{self.log_prefix} Prompt组件 '{self.prompt_name}' 初始化完成") From 2f46794a64f61fbddb4229e707237bc0628250d7 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Thu, 13 Nov 2025 18:38:47 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat(statistic):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8C=89=20provider=20=E7=BB=9F=E8=AE=A1=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/utils/statistic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chat/utils/statistic.py b/src/chat/utils/statistic.py index 5b1ce7826..3cf604675 100644 --- a/src/chat/utils/statistic.py +++ b/src/chat/utils/statistic.py @@ -411,6 +411,7 @@ class StatisticOutputTask(AsyncTask): (REQ_CNT_BY_USER, "user"), (REQ_CNT_BY_MODEL, "model"), (REQ_CNT_BY_MODULE, "module"), + (REQ_CNT_BY_PROVIDER, "provider"), ]: time_cost_key = f"TIME_COST_BY_{items.upper()}" avg_key = f"AVG_TIME_COST_BY_{items.upper()}" From 38ec114c8178884210130bff3319513d6dd5d378 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Thu, 13 Nov 2025 18:46:36 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(system):=20=E4=B8=BA=20system=20?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E6=B7=BB=E5=8A=A0=20prompt=20=E5=AD=90?= =?UTF-8?q?=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/built_in/system_management/plugin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/built_in/system_management/plugin.py b/src/plugins/built_in/system_management/plugin.py index e3c7ddeb6..ff5a0f2bf 100644 --- a/src/plugins/built_in/system_management/plugin.py +++ b/src/plugins/built_in/system_management/plugin.py @@ -60,6 +60,8 @@ class SystemCommand(PlusCommand): await self._handle_schedule_commands(remaining_args) elif subcommand in ["help", "帮助"]: await self._show_help("all") + elif subcommand in ["prompt","提示词"]: + await self._handle_prompt_commands(remaining_args) else: await self.send_text(f"❌ 未知的子命令: {subcommand}\n使用 /system help 查看帮助") From 028bcf7fbc488043b08329801b8e1e36c24f6f14 Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Thu, 13 Nov 2025 19:34:16 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(planner):=20=E4=BF=AE=E5=A4=8D=20Focus?= =?UTF-8?q?=20=E6=A8=A1=E5=BC=8F=E4=B8=8B=E7=9A=84=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../built_in/affinity_flow_chatter/planner/planner.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/plugins/built_in/affinity_flow_chatter/planner/planner.py b/src/plugins/built_in/affinity_flow_chatter/planner/planner.py index 301bafb57..0ac27bb93 100644 --- a/src/plugins/built_in/affinity_flow_chatter/planner/planner.py +++ b/src/plugins/built_in/affinity_flow_chatter/planner/planner.py @@ -156,9 +156,6 @@ class ChatterActionPlanner: except Exception as e: logger.warning(f"Focus模式 - 处理消息 {message.message_id} 失败: {e}") - message.interest_value = 0.0 - message.should_reply = False - message.should_act = False # 2. 检查兴趣度是否达到非回复动作阈值 non_reply_action_interest_threshold = global_config.affinity_flow.non_reply_action_interest_threshold @@ -202,9 +199,9 @@ class ChatterActionPlanner: filtered_plan = await plan_filter.filter(initial_plan) # 检查reply动作是否可用 - reply_action_available = "reply" in available_actions or "respond" in available_actions - if filtered_plan.decided_actions and not reply_action_available: - logger.info("Focus模式 - 回复动作不可用,移除所有回复相关动作") + has_reply_action = "reply" in available_actions or "respond" in available_actions + if filtered_plan.decided_actions and has_reply_action and reply_not_available: + logger.info("Focus模式 - 未达到回复动作阈值,移除所有回复相关动作") filtered_plan.decided_actions = [ action for action in filtered_plan.decided_actions if action.action_type not in ["reply", "respond"]