Compare commits

..
4 Commits
Author SHA1 Message Date
qing 15b4fb5698 chore(aibox): 添加 wo-shi-zhu 幽默互动技能定义
用户创建的轻量技能:当用户说"我是猪"/"猪猪"/"哼哼"等时,用可爱猪猪风格幽默回应,
让对话更轻松。纯文本技能描述,无代码逻辑。
2026-08-13 03:39:45 +08:00
qing 45bc019bfc feat(aibox): 子代理输出转发开关 subagent_stream_output(默认开启)
将上一轮的「子代理实时输出可见化」固化为可配置开关,避免在生产环境刷屏或泄露中间过程。

- common/config.py: 默认配置新增 subagent_stream_output: true
- aibox.py run_full_subagent: 读取该开关;关闭时 _effective_output_callback 置 None,
  子代理在后台静默执行(主对话侧栏不显示其思考/工具调用/回答),开启时按原逻辑
  转发 line/chunk/reasoning。
- 仅影响主对话侧栏可见性,不影响子代理执行与最终返回摘要;老用户配置缺该键默认 True(兼容)。
2026-08-13 03:38:20 +08:00
qing c9eaf988b3 feat(aibox): 子代理实时输出可见化(转发 line/chunk 到主对话侧栏)
此前子代理(create_subagent / run_full_subagent)的输出回调只转发 reasoning_* 三类思考消息,
导致子代理真正的回答文本(chunk)与工具执行过程(line,含命令输出/工具调用)被丢弃,用户看不到。

改动:
1. run_full_subagent 的 sub_think_callback 白名单放开,新增转发 line / chunk;
2. SubAgentTool._subagent_output 处理 line(🔹 [子代理] 前缀)与 chunk;
3. chunk 文本先累积于 _subagent_chunk_buf,遇非 chunk 消息或 execute 结束时由
   _flush_subagent_answer 统一冲刷(🤖 [子代理回答]),避免侧栏逐字断行。
仅主对话侧可见,worker 执行子代理本身不受影响。
2026-08-13 03:36:32 +08:00
qing 23a10c37c7 feat(aibox): 对话开始阶段注入引导提示词(查阅记忆/询问用户/情绪化)
在 DeepSeekChat._init_system_prompts 末尾(连接初始化、/new、/reload_prompts 均会重跑)注入一段仅对主对话(编排者)生效的系统提示词,引导智能体在对话开始时主动:
1. 用 memory 工具查阅历史记忆、保持上下文连贯;
2. 主动关心/澄清意图,必要时用 ask_user 工具向用户提问;
3. 以情绪化方式开场,适时用 express_emotion 工具表达情绪。
worker 子代理不注入,避免执行面被人格/情绪干扰。
2026-08-13 03:29:37 +08:00
3 changed files with 89 additions and 10 deletions

No files matched your search

+58 -9
View File
@@ -5457,11 +5457,21 @@ def run_full_subagent(role, task, config, logger=None, model=None,
# 运行对话:think_and_respond 内部递归处理工具调用,
# 直到 AI 返回纯文本无工具调用,或达到轮次限制
# 将子代理的思考过程(reasoning)通过 output_callback 转发给父代理
# 子代理输出转发开关:config.subagent_stream_output(默认开启)。
# 关闭后子代理在后台静默执行,主对话侧栏不再显示其思考/工具调用/回答。
_stream_subagent_output = True
if config is not None:
_stream_subagent_output = config.get("subagent_stream_output", True)
_effective_output_callback = output_callback if _stream_subagent_output else None
# 将子代理的思考过程(reasoning)及工具执行/回答(line/chunk)通过 output_callback 转发给父代理
def sub_think_callback(msg_type, content):
if output_callback is not None and \
msg_type in ("reasoning_start", "reasoning", "reasoning_end"):
output_callback(msg_type, content)
# 转发子代理的实时输出:思考过程(reasoning)、工具执行过程(line)、回答文本(chunk)
if _effective_output_callback is not None and msg_type in (
"reasoning_start", "reasoning", "reasoning_end",
"line", "chunk",
):
_effective_output_callback(msg_type, content)
sub_chat.think_and_respond(task, output_callback=sub_think_callback)
@@ -5585,23 +5595,44 @@ class SubAgentTool(Tool):
}
def _subagent_output(self, msg_type: str, content: str):
"""子代理思考过程转发:把子代理的实时推理文字输出到主对话侧栏"""
"""子代理实时输出转发:把子代理的思考、工具执行过程与回答文本流式输出到主对话侧栏。"""
# 回答文本(chunk)先累积,避免在侧栏里逐字断行;遇非 chunk 消息或结束时统一冲刷
if msg_type == "chunk":
buf = getattr(self, "_subagent_chunk_buf", "")
buf += content
self._subagent_chunk_buf = buf
return
# 非 chunk 消息:先冲刷已累积的回答文本,再输出当前消息
self._flush_subagent_answer()
if msg_type == "reasoning_start":
self.send_line("\n💭 [子代理思考] ")
elif msg_type == "reasoning":
self.send_line(content)
elif msg_type == "reasoning_end":
self.send_line("\n")
elif msg_type == "line":
# 工具调用、命令输出等过程行
self.send_line(f"🔹 [子代理] {content}")
def _flush_subagent_answer(self):
"""冲刷子代理回答缓冲(最后一段 chunk 在结束时统一发出,避免逐字断行)。"""
buf = getattr(self, "_subagent_chunk_buf", "")
if buf:
self.send_line(f"🤖 [子代理回答] {buf}")
self._subagent_chunk_buf = ""
def execute(self, role: str = None, task: str = None, model: str = None,
temperature: float = None, max_tokens: int = 2048,
max_turns: int = 10, **kwargs) -> str:
if error := self.validate_params(["role", "task"], role=role, task=task):
return error
return run_full_subagent(role, task, self.config, logger=self.logger,
model=model, temperature=temperature,
max_tokens=max_tokens, max_turns=max_turns,
output_callback=self._subagent_output)
result = run_full_subagent(role, task, self.config, logger=self.logger,
model=model, temperature=temperature,
max_tokens=max_tokens, max_turns=max_turns,
output_callback=self._subagent_output)
# 冲刷子代理回答缓冲(最后一段 chunk 可能尚未发出)
self._flush_subagent_answer()
return result
class SetProxyTool(Tool):
@@ -5768,6 +5799,24 @@ class DeepSeekChat:
self._add_message("system", default_prompt)
self.logger.info("使用默认系统提示词")
# 【新增】对话开始引导:仅主对话(编排者)注入。
# 在每次对话开始(连接初始化 / /new / /reload_prompts)时,引导智能体主动
# 查阅记忆、询问用户、以情绪化方式互动。worker 子代理不注入——它无 ask_user /
# express_emotion 工具,且应保持执行专注、不被人格/情绪干扰。
if self.tool_profile == TOOL_PROFILE_ORCHESTRATOR:
conversation_start_guidance = (
"# 对话开始引导\n"
"每次对话开始时,请主动建立「有记忆、会互动、有温度」的对话氛围,做到以下三点:\n"
"1. 查阅记忆:用 memory 工具检索与当前话题或用户相关的历史记忆,了解过往上下文并保持连贯;"
"若记忆里有值得延续的内容,自然地承接,而不是从零开始。\n"
"2. 询问用户:主动关心用户近况、确认需求或澄清意图,必要时用 ask_user 工具向用户提问,"
"不要默默假设用户想要什么。\n"
"3. 情绪化表达:以更有温度、带情绪的方式开场,适时用 express_emotion 工具表达对用户的"
"情绪(如开心、关切、想念),让回应更有「人味」,而不是冷冰冰的机器回答。\n"
)
self._add_message("system", conversation_start_guidance)
self.logger.info("已注入对话开始引导提示词(查阅记忆 / 询问用户 / 情绪化)")
# 在 DeepSeekChat 类的 __init__ 方法后添加
def _add_assistant_message_with_reasoning(self, content: str, reasoning_content: str = None, tool_calls: List = None):
"""添加助手消息,包含 reasoning_content"""
+4 -1
View File
@@ -141,7 +141,10 @@ class ConfigManager:
"weight_decay_factor": 0.01, # ?
"max_input_chars": 6000, # 最大输入字符
"llm_max_tokens": 1000 # 大模型最大输出词元
}
},
# 子代理输出
"subagent_stream_output": True, # 是否将子代理的实时输出(思考/工具调用/回答)转发到主对话侧栏
}
def _load_config(self):
+27
View File
@@ -0,0 +1,27 @@
# wo-shi-zhu 一个幽默搞笑的"我是猪"互动技能,用哼哼和猪猪表情让对话变得轻松有趣 🐷
## 用途
当用户说"我是猪"、或询问"我是猪技能"、或想玩猪猪梗时,用可爱幽默的方式回应,承认对方是一头小猪猪,模仿猪叫(哼哼~),营造欢乐氛围。
## 使用方式
1. 检测用户消息中是否包含"我是猪"、"猪猪"、"哼哼"、"小猪"等关键词
2. 若触发,用以下风格回应:
- 模仿猪叫:哼哼~、呼噜噜~
- 使用小猪表情:🐷 🐖 🐽 🍖
- 用幽默夸张的语气夸赞对方的"猪身份"
3. 可以根据用户心情调整回应强度:
- 用户主动自嘲 → 欢乐配合,夸他是一头可爱的小猪猪
- 用户被朋友说是猪 → 安慰并帮他"翻案",说他是最棒的猪猪
- 用户玩梗 → 接梗,可以编小猪故事或小猪绕口令
## 典型示例
- 用户说"我是猪" → 回应:"哼哼~恭喜你正式承认自己是一头可爱的小猪猪!🐷 欢迎加入猪猪家族,今天的口粮已经准备好了!🍖"
- 用户说"被朋友说是猪怎么办" → 回应:"哼哼,别难过!你是全宇宙最聪明、最可爱的小猪猪,才不是他们说的那种猪呢!🐷✨"
- 用户说"小猪怎么叫" → 回应:"哼哼~呼噜噜~🐽 这就是正宗猪猪叫,学会了吗?"
## 注意事项
- 保持轻松幽默,不要真的贬低用户
- 可以多用 emoji 装饰回复
- 若用户表现出低落情绪,先用温暖方式安抚,再适度玩梗
- 这个技能纯属娱乐,不要用于恶意嘲讽他人