# trss-agents-plugin **Repository Path**: YunXi-67/trss-agent-plugin ## Basic Information - **Project Name**: trss-agents-plugin - **Description**: 基于TRSS-Yunzai的AI Agent插件框架: LLM对话·工具调用·长期记忆·MCP·工具进化 - **Primary Language**: NodeJS - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-07-22 - **Last Updated**: 2026-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: trss, agents ## README
# 🤖 TRSS AI Agent Plugin > A modular AI Agent runtime for TRSS-Yunzai — LLM · Tool Calling · Memory · MCP · and self-evolving tools. **基于 [TRSS-Yunzai](https://github.com/TimeRainStarSky/Yunzai) / [Miao-Yunzai](https://github.com/Le-niao/Yunzai-Bot) 的 AI Agent 插件框架** —— 不是普通插件,而是一套可演化的 Agent Runtime:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端(E2B 沙箱) · 图片渲染,外加**工具进化(Tool Evolution)**等差异化能力。 一个插件打通:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端(E2B 沙箱) · 图片渲染 License Platform Runtime AI Agent QQ Group **QQ 群**:[960179589](https://qm.qq.com/q/960179589) | **作者 QQ**:3891977697
--- > ## 🌿 分支说明(先看) > > - **`master` 为稳定版**:核心对话(多模型聊天 / 工具调用 / 记忆 / 人设 / 图片渲染 / MCP / 群管)稳定可用,**只接收 bug 修复**。 > - **`beta` 为 beta 测试分支**:新功能上线、或 Agents 底层改动(可能影响插件稳定性的改动)**优先推送到 `beta`**,验证稳定后会逐步合并进 `master`。 > - 🧪 **想尝鲜且有一点自行解决问题能力的用户,可以部署 `beta` 分支**体验最新能力;生产/追求稳定请用 `master`。 > - 维护约定:**bug 修复同时推送到 `master` 与 `beta`**,保持两个分支修复进度一致;新功能/底层改动只进 `beta`、不进 `master`。 --- > ## 📌 重要提示(先看) > > - 🎭 **表情包功能已恢复**:支持自动发现(群聊被动采集 → 视觉判定+打标 → 入库)+ 手动安装(manifest 驱动)+ LLM 自主引用 `[sticker:名称]`。配置 `agent.sticker` 开启。 > - 🧪 **深度搜索 / 深度研究(`#研究`)为早期功能**:依赖联网检索 + 多轮子代理编排,受搜索源、模型能力、token 消耗影响,效果可能不稳定甚至不可用。 > - ⚠️ **终端执行为沙箱能力**:默认关闭;开启 `agent.sandbox.mode: e2b` + `apiKey`(命令在 E2B 微虚机内执行)即视为自担风险。沙箱服务端二选一:**E2B 云托管**(只填 apiKey)或**自托管**(必须有 KVM——腾讯云轻量等普通云主机不行,见「自托管安装」)。 > - ✅ **核心对话(多模型聊天 / 工具调用 / 记忆 / 人设 / 图片渲染 / MCP / 群管)稳定可用**,请以核心为主。 --- ## ✨ 项目亮点 - **一插件打通全链路**:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端 · 图片渲染,无需东拼西凑。 - **ReAct 内核 + 自我反思/自纠**:最终回复交付前门控自检(完整性 / 准确性 / 一致性),发现问题自动回环修正;多层频率闸防"每条都带表情"的 AI 感。 - **双协议多模型**:OpenAI / Anthropic 兼容,一行配置接 DeepSeek / Kimi / MiMo / 通义 / 智谱 / Gemini;视觉子模型让无视觉的主模型也能识图。 - **渐进式披露 + 结构化 prompt**:技能按需加载、工具目录速查、分层 system prompt(执行取向 / 服务准则 / 安全护栏),兼顾能力与上下文成本。 - **文件即真相的记忆**:`MEMORY.md` / `USER.md` 人可读可编辑 + `memory_search` 主动召回,跨会话不失忆、不串档。 - **安全纵深**:工具 RBAC + 主人审批 + 注入防御 + 高危执行面隔离(终端与工具进化代码跑在 E2B 沙箱,宿主无 shell 执行面),高危动作不裸奔。 - **配置热加载 + 锅巴适配**:改配置即生效、免重启;锅巴 Web 面板可视化编辑。 - **回复默认渲染成精美图片**:markdown → 浅色卡片图(标题 / 列表 / 代码高亮 / 表格 / 引用全支持),失败退文本。 - **🧬 工具进化(Tool Evolution)**:Agent 经 LLM 生成新工具 → typescript AST 静态门 → 沙箱行为验证 → 主人审批上线,形成可验证 / 可回滚 / 权限不可自扩的工具生命周期(生成→验证→晋升→淘汰闭环)。 --- ## 📌 功能一览 | 能力 | 说明 | 状态 | | --- | --- | --- | | 💬 多模型对话 | OpenAI / Anthropic 双协议,接 DeepSeek / Kimi / MiMo / 通义 / 智谱 / Gemini 等 | ✅ 稳定 | | 🖼️ 图片渲染回复 | markdown → 精美**浅色卡片**图片(完整语法 + 代码高亮 + 底部会话/对话id),失败退文本 | ✅ 稳定 | | 🔧 工具调用 | ReAct 内核、并行调用、RBAC + 主人审批、工具开发 SDK | ✅ 稳定 | | 🧠 长期记忆 | MEMORY.md/USER.md 人可编辑 + `memory_search` 主动召回(参考 OpenClaw) | ✅ 稳定 | | 🎭 人设系统 | 内置 6 角色 + 自建,替换身份层不缩水工具/记忆 | ✅ 稳定 | | 🖼️ 多模态识图 | 视觉子模型(主模型无视觉时图转文) | ✅ 稳定 | | 🔌 MCP | 完整 MCP 客户端(stdio / HTTP)、多服务端、按工具 RBAC | ✅ 稳定 | | 👥 群聊工具 | 群信息 / 群管理 / 米游社搜索 | ✅ 稳定 | | 📥 媒体下载 | 基于 yt-dlp 的视频/音频下载(受约束,仅主人),支持 YouTube/B站/抖音等 1000+ 站点 | ✅ 稳定 | | 🗣️ 语音合成 | 四家服务商:IndexTTS 2.5(本地)/ 豆包 / MiniMax / MiMo;`tts_speak` 点播 + 自动语音;情绪统一由 LLM 结合上下文判定(8 维向量 → 各服务商语音指令/情感标签);pro/max 档位 | ✅ 可用 | | 💻 终端执行 | **E2B 沙箱执行**(Firecracker microVM;全员可用 + 出口白名单 + 命令数/并发上限);服务端用 **E2B 云**或**自托管(需 KVM,普通云主机不支持)** | ⚠️ 高危可选 | | 🌐 浏览器自动化 | **Stagehand**:goto/observe/extract/act 自然语言原语,本地或 Browserbase 云,会话跨调用保持 | 🧪 早期 | | 🎭 表情包 | 自动发现(群聊被动采集→视觉打标→入库)+ 手动安装 + LLM 自主引用 `[sticker:名称]` | ✅ 稳定 | | 🤖 伪人模式 | 群聊环境参与者:旁听→门控→Planner 决策→Replyer 自然回复(参照 MaiBot) | 🧪 早期 | | 💬 私聊对话 | 私聊触发对话(默认**关闭**:`agent.privateChat=false`;开启后私聊任何消息直接触发,独立会话与记忆) | ✅ 稳定 | | 🌐 代理访问 | HTTP/SOCKS 代理(国内服务器访问 GPT/Gemini 等海外 LLM) | ✅ 稳定 | | 🔁 回退模型 | 主模型失败自动依次尝试 `fallbackModels`(同 provider) | ✅ 稳定 | | 📂 日志分文件 | 按会话分文件 + 图片底部会话/对话id + `#上报错误` 打包发主人 | ✅ 稳定 | | 🔍 统一搜索 | Tavily/Exa/Perplexity/Brave → SearXNG → DDG 兜底;`web_search` 多角度并行查询 + 去重合并,内置交叉/对抗验证纪律(防信息茧房) | ✅ 稳定 | | 📊 示意图生成 | 流程图/架构图/时序图/状态图/ER/思维导图:LLM 语义结构 → 自托管 Kroki D2 → 高清 PNG(文字/连线精确,非文生图) | ✅ 稳定 | | 📚 深度研究 | `#研究` 五阶段管线(规划→检索→综合→引用→评估) | 🧪 早期 | | 🧬 工具进化 | LLM 生成候选 → AST 门 + 隔离执行面验证 → 审批上线(版本化 / 可回滚 / 安全闸) | 🧪 早期 | --- ## 🧬 工具进化(Tool Evolution) > Agent 不再只从固定工具列表中选择——它能**生成新工具、验证、审批上线、持续改进与淘汰**,形成可演化的工具库。这是本插件相对普通 Agent 框架的核心差异点,也是搜索词 `tool evolution agent` 的入口。 **完整生命周期**(安全纵深,五阶段): ``` #进化工具 <能力描述> → LLM 生成(json_schema 结构化) → typescript AST 静态门(禁 require / child_process / process.env / eval / 一切 import;危险候选不入库) → 隔离行为验证(E2B 沙箱 / 本地子进程双档 + 测试断言 + 性能/超时门) → #采纳工具 (master 审批)→ stable + 注入 → agent 经 tool_search 调用 → 调用埋点 → 适应度 / 失败聚类 → #工具健康 检测 → #淘汰工具 下线 ``` **安全原则**(不可妥协): - ① **生成闸**:只允许 `sideEffects ∈ {none, read}`;联网 / 发消息 / 删库等**固定受信适配器永不自动生成** - ② **可信基不可被工具进化**:DB / 验证器 / 沙箱 / 审批 / 审计由人维护,工具不能改 - ③ **版本不可变 + 审计 + 权限单调不增 + 安全硬否决**(一票否决,非权重) **命令族**(均 master):`#进化工具` / `#工具进化列表` / `#采纳工具` / `#淘汰工具` / `#工具健康` + Web「工具进化」管理面板。 --- ## 📑 目录 - [✨ 项目亮点](#-项目亮点) - [📦 安装](#-安装) - [🚀 快速开始](#-快速开始) - [⚙️ 详细配置](#️-详细配置pluginsagents-pluginconfigconfigyaml) - [🎮 指令](#-指令) - [🧩 扩展开发(工具 / 技能)](开发指南.md) - [🧠 记忆体系](#-记忆体系参考-openclaw文件即真相) - [💻 终端执行(E2B 沙箱)](#-终端执行e2b-沙箱--全员可用) - [🎭 表情包](#-表情包llm-自主附带) - [🏗️ 架构](#️-架构) - [🔧 日志](#-日志与排查) - [📞 联系](#-联系) --- ## ⚠️ 安全声明 本插件提供**终端(shell)执行能力**,命令跑在 **E2B 沙箱**(Firecracker microVM)里: - 命令在**独立微虚机内执行**:宿主文件/进程不可见,网络出口按 `agent.sandbox.network.allowOut` 白名单收紧(默认只放行包管理器与 `api.openai.com`)。 - terminal **全员可用**(无身份门槛、无验证码认领):每个会话(群/用户/对话)独占一个沙箱、文件系统互不可见;沙箱化后**不再有逐条 `#确认` 审批与命令黑名单**(破坏面已被 microVM 限制),成本由单会话命令数上限、单命令超时上限与并发沙箱上限兜底。 - **终端默认关闭**(`agent.sandbox.mode` 默认 `off`,此时 terminal 工具**根本不注册**),需自行准备 E2B(自托管或云)并填 `apiKey` 后开启。 - **连不上 E2B 时一律拒绝执行**(fail-closed),**绝不回退到主机执行**——本插件已删除宿主 shell 执行面。 - **开启 `agent.sandbox.mode: e2b` 即表示你已知晓上述风险、同意自行承担一切后果,与开发者无关。** 沙箱逃逸类漏洞、配额/账单消耗、主人账号被盗导致的沙箱操作权,均需自行评估;开发者不作任何担保。 > 如不接受该风险,请保持 `agent.sandbox.mode: off`(默认)。此时本插件不涉及任何 shell 执行(含沙箱)。 > > **升级注意**:旧配置 `agent.terminal.*`(`enable`/`maxTimeout`/`blocklist`/`skipConfirm`)已废弃。Config 的自愈机制只增不删,所以旧键会留在你的 `config/config.yaml` 里但**不再被读取**;启动时会打印一条迁移警告,请手工删除该段并改配 `agent.sandbox`。 --- ## 📦 安装 ```bash # Gitee(国内推荐): git clone https://gitee.com/YunXi-67/trss-agent-plugin.git ./plugins/agents-plugin # 或 GitHub: git clone https://github.com/yunhai89/trss-agent-plugin.git ./plugins/agents-plugin cd ./plugins/agents-plugin && npm install # 安装 markdown 渲染依赖(marked / highlight.js) ``` > 除 markdown 渲染(marked / marked-highlight / highlight.js,需在插件目录 `npm install`)外,其余依赖随 Yunzai 提供。`#agents更新`(git pull)后若 package.json 有变动,需重跑一次 `npm install`。 > 重启 Yunzai 后,首次启动自动在**插件自己的** `plugins/agents-plugin/config/config.yaml` 生成配置,填入 API Key 即可使用。 ### 🌿 安装稳定版 / beta 测试版 - **稳定版(推荐)**:直接使用上面的克隆命令(默认 `master` 分支)。 - **beta 测试版(尝鲜)**:新功能与 Agents 底层改动会**先进入 `beta`**,验证稳定后再逐步合并进 `master`。安装时加 `-b beta`: ```bash # Gitee(国内推荐): git clone -b beta https://gitee.com/YunXi-67/trss-agent-plugin.git ./plugins/agents-plugin # 或 GitHub: git clone -b beta https://github.com/yunhai89/trss-agent-plugin.git ./plugins/agents-plugin cd ./plugins/agents-plugin && npm install ``` #### 已有安装切换分支 ```bash cd ./plugins/agents-plugin git fetch origin git checkout beta # 切到 beta 测试分支 git pull origin beta # 拉取最新代码;若本地有冲突可改用:git reset --hard origin/beta npm install # package.json 有变动时需重跑 ``` 切回稳定版:`git checkout master && git pull origin master`。 > ⚠️ 切换 / 更新后建议**重启 Yunzai**(或主人发 `#agents重载`)以重建运行时。你的配置(`config/config.yaml`)与 `tools/` 自研工具包**不在版本控制内**,切换分支不会覆盖。 > 维护约定:**bug 修复同时更新 `master` 与 `beta`**;新功能 / 底层改动只进 `beta`(详见页首「🌿 分支说明」)。 ### 🖼️ 图片回复(默认开启) 机器人回复**默认渲染成精美浅色卡片图片**(完整 markdown + 代码语法高亮),渲染失败自动退文本。配置 `agent.reply.mode`: - `image`(默认):markdown → 浅色卡片图片(标题/列表/代码高亮/表格/引用全支持) - `text`:纯文本回复 > 配置文件在插件目录内(不在 Yunzai 根)。若你之前用的是旧版 `Yunzai/config/agents-plugin.yaml`,首次加载会**自动迁移**到插件目录并删除旧文件(apiKey/masters 等全部保留)。 > **支持热加载**:改完配置保存即可,**无需重启 Yunzai**——下次对话自动用新配置重建运行时(provider/model/tools/skills/mcp)。也可发 `#agents重载`(主人)立即重建。 > > **锅巴(Guoba)适配**:已支持。安装 [Guoba-Plugin](https://gitee.com/guoba-yunzai/guoba-plugin) 后,`#锅巴登录` 进入 Web 面板即可图形化编辑本插件配置;保存后**自动热加载**。适配文件为插件根 `guoba.support.js`。 --- ## 🚀 快速开始 **推荐路径**:打开 Web 配置中心(主人私聊 `#agents登录` 取访问地址),在 **厂商配置** 添加厂商(接口地址 + Key)→ **模型列表** 在该厂商下添加模型 → **基础 / 模型** 选中这两个条目。保存即热加载。 群里 **@机器人** 或发 **`#ai 你好`** 即可对话。 基础模型是**引用式**的:config.yaml 里用 `providerId` + `modelId` 指向「厂商配置 / 模型列表」的条目,不再单独填接入参数。手写配置的等价写法: ```yaml agent: llmProviders: # 厂商配置(协议/预设/地址/Key 都在这里) - id: pmain name: DeepSeek protocol: openai # 或 anthropic / gemini preset: deepseek # 厂商预设:openai/deepseek/gemini/dashscope/zhipu/moonshot/mimo/minimax 等 baseURL: "" apiKey: "sk-xxx" # ★必填 llmModels: # 模型列表(挂在某厂商下) - id: mchat name: 主力 providerId: pmain model: "deepseek-chat" providerId: pmain # ← 基础模型选哪个厂商 modelId: mchat # ← 基础模型选哪个模型 ``` > 老配置(只有 `protocol`/`preset`/`baseURL`/`apiKey`/`model` 五个扁平字段)**首次加载会自动迁移**:按原接入信息生成一条厂商 + 一条模型条目,并让上面两个引用指向它们,无需手工重配。迁移后这五个字段变成只读镜像(由上层引用解析回填),手改会在下次加载被覆盖。 --- ## ⚙️ 详细配置(`plugins/agents-plugin/config/config.yaml`) > 配置文件不含注释(保持整洁),所有字段含义在此说明。未用到的字段留空即可。 ### 基础 | 字段 | 说明 | | --- | --- | | `debug` | `true` 打开详细日志(工具入参/每轮 token/搜索词等),排查时开启 | | `prefix` | 命令前缀(保留备用) | ### `agent` —— 对话与模型 | 字段 | 默认 | 说明 | | --- | --- | --- | | `trigger` | `at` | 触发模式:`at`(艾特) / `command`(触发词) / `both` | | `triggerCommand` | `#ai` | `trigger` 为 command/both 时的触发词 | | `providerId` | 空 | **★必填** 基础模型选用哪个厂商条目(见下方 ↴ `llmProviders`) | | `modelId` | 空 | **★必填** 基础模型选用哪个模型条目(须挂在上述厂商下) | | `llmProviders` | `[]` | 厂商清单 `[{ id, name, protocol, preset, baseURL, apiKey }]`;没有“默认厂商”,被 `providerId` 选中的那个就是主接入 | | `llmModels` | `[]` | 模型清单 `[{ id, name, providerId, model, temperature, maxTokens, thinking, note }]`;`thinking/温度/maxTokens` 在被主对话链路使用时覆盖全局 | | `protocol` / `preset` / `baseURL` / `apiKey` / `model` | 镜像 | 上面引用的**解析结果**,加载时自动回填;勿手改,改厂商 Key / 换模型会自动跟随 | | `utilityModel` | 空 | 播报等旁路小模型(留空=沿用主模型);可填任意已注册厂商的模型(运行时按注册表解析端点,不再局限主厂商) | | `reasoningFields` | `[]` | 推理字段归一化(如 `["reasoning_content"]`),preset 通常已带 | | `maxTurns` | `50` | 单次对话工具调用轮次预算 | | `temperature` | 空 | 采样温度 | | `maxTokens` | 空 | 单次回复最大 token(留空=厂商默认;Anthropic 默认 4096) | | `contextWindow` | 空 | 模型上下文窗口 token 数(如 `32000`);超 80% 自动压缩历史、保留首条意图 | | `maxToolResultChars` | `4000` | 单条工具结果字符上限,超长截断防上下文膨胀 | | `keepReasoning` | `false` | 是否把推理(`reasoning_content`)回灌历史;默认 `false` 省 context。thinking 模式下带工具调用的轮次按协议必需始终回传(不受此开关影响),否则上游会报 "reasoning_content must be passed back" | | `stream` | `false` | 逐字流式输出(依赖适配器、不稳,默认关) | | `progress` | `true` | 工具调用时推送节流进度消息(消除"干等",默认开) | | `progressRecall` | `3` | 进度消息多少秒后自动撤回(适配器不支持则忽略) | | `reply.mode` | `image` | 回复渲染:`image`(markdown→浅色图片,默认)/ `text`(纯文本) | | `reply.atSender` | `true` | 群聊回复时艾特发言人(私聊不艾特) | | `reply.narrate` | `true` | 中途播报:模型调工具时附带的思路/进展文本自动转发给用户(参考 OpenClaw) | | `reply.renderScale` | `2` | 回复图片渲染倍率(deviceScaleFactor,2=高清;越大越清晰但越耗内存/体积) | | `thinking` | 空 | 思考模式(手动),如 `{ type: "enabled", budget_tokens: 16000 }` | | `thinkingAuto` | 关 | 思考自动决策:`{ enable, classifier, model, timeoutMs, maxBudget, budgets:{low,medium,high}, style }`。判档方式 `classifier`:`auto`=规则不确定时用小模型判(省调用)/`always`=总是小模型/`off`=纯规则;小模型带超时、缓存,失败自动回退规则,不阻塞对话。档位→厂商原生字段(MiMo/Kimi/GLM/豆包→`thinking`、DeepSeek→`thinking`+`reasoning_effort`、Qwen→`enable_thinking`+`thinking_budget`、MiniMax→`adaptive`、Anthropic→`budget_tokens`、o/GPT→`reasoning_effort`、Gemini→`thinking_level`)。模型级 `thinking` 显式覆盖仍优先 | | `memoryLimits` | 空 | 声明式记忆字符上限,如 `{ memory: 2200, user: 1375 }` | | `systemPrompt` | 空 | 默认身份 system prompt(留空用富默认身份;被人设覆盖时失效) | | `chatPermission` | `master` | `#ai` 命令权限:`master`/`admin`/`owner`/`all` | | `privateChat` | `false` | 私聊是否触发对话;默认关(私聊不响应,仅群内 @/命令触发),设 `true` 开启 | | `masters` | `[]` | 接收审批通知的 master QQ 号列表 | | `masterSkipConfirm` | `false` | ⚠️高危:主人发起的确认类工具(stagehand act 等)免 `#确认` 直接执行(仅主人,控制台有日志不在聊天提示;denylist 仍硬拦)。注:terminal 已沙箱化,不走审批 | | `confirmTimeout` | `300` | 审批超时自动拒绝(秒) | | `guardAction` | `flag` | 注入防御动作:`block`(拦截)/`flag`(隔离标注)/`sanitize`(脱敏) | | `guardSensitivity` | `medium` | 防御灵敏度:`low`(0.95)/`medium`(0.7)/`high`(0.5) | | `redactSecrets` | `true` | 发送前脱敏:屏蔽回复中的 API Key / token 等敏感信息 | ### `agent.policy` —— RBAC 策略 ```yaml policy: categoryMin: message: 1 # 覆盖内置类别最低角色 mcp_write: 2 # 自定义类别(如 MCP 写工具需群管以上) ``` 内置类别阶梯:`query:0` / `personal:0` / `message:1` / `group_manage:2` / `system:3`。角色:`member 🧪 搜索为早期功能,效果取决于搜索源可用性。任填一个 key 即用该源;都不填回退 SearXNG,再兜底 DDG(始终可用)。 **防信息茧房的搜索纪律(内置于系统提示,无需配置)**:Agent 被告知"关键事实至少两个独立来源交叉验证、下结论前先找反证、争议话题并列双方依据、冲突不静默选一个";`web_search` 支持一次并行发 2~4 个不同角度的 `queries`(换措辞/换来源/官方一手/找反证),结果按 URL 去重合并并标注来源与时间,部分查询失败会显式提示覆盖缺口;核对一手页面用 `web_extract` 读正文(摘要可能断章取义)。 ```yaml search: tavily: { apiKey: "" } exa: { apiKey: "" } perplexity: { apiKey: "" } brave: { apiKey: "" } searxng: { url: "" } # 如 http://localhost:8080 ddg: true # 本地 DDG 兜底(默认开) ``` ### `agent.diagram` —— 示意图生成(diagram_render) > Agent 对话里说「画一下 XX 的流程图/架构图/时序图」即可生图。**不用文生图模型**——文字、连线、层级精确可靠: > LLM 只提交语义结构(节点/连线/分组/时序消息),插件确定性编译为 D2,由**自托管 Kroki** 容器渲染 SVG, > 经安全检查后用 resvg 转高清 PNG(默认宽 1600、2x 清晰度、内置中文字体)随回复发送。 > > - **支持图类型**:flowchart / architecture(容器分组)/ sequence / state / class / er / mindmap > - **主题**:paper-blue(默认)/ soft-pastel / technical / midnight(深色)/ sketch(手绘,仅 D2) > - **安全边界**:LLM 不能提交 SVG/HTML/坐标/路径;默认禁用公共 Kroki(用户内容不出内网);SVG 输出按不可信内容检查(拒脚本/外链/实体);临时文件只写 `data/diagram/`(内容哈希命名 + TTL 清理) > - **容错**:Kroki 不可用 → 连接超时/熔断/结构化失败(可配本地 `beautiful-mermaid` 回退),绝不挂死 Agent 或让用户无回复 **部署 Kroki 容器**(默认引擎依赖,一次性): ```bash # 推荐:一键脚本(缺 Docker 自动安装、镜像国内加速、健康检查) sh plugins/agents-plugin/scripts/install-kroki.sh # 或手动(已装 Docker): docker compose -f docs/deploy/kroki-compose.yaml up -d # 然后保持 agent.diagram.kroki.endpoint: http://127.0.0.1:8000 ``` > 脚本默认在缺少 Docker 时用发行版包管理器自动安装并启动(apt/dnf/yum/apk); > 非交互环境需显式 `-y` 或 `DOCKER_ASSUME_YES=1`,`DOCKER_AUTO_INSTALL=0` 可关闭自动安装只做检测。 ```yaml diagram: enable: true renderer: kroki # 自托管 Kroki 渲染 D2 fallbackRenderer: none # Kroki 失败的本地回退:none | beautiful-mermaid defaultTheme: paper-blue # paper-blue | soft-pastel | technical | midnight | sketch defaultFormat: png # png | svg(svg 以可编辑源文件发送) timeoutMs: 15000 # 渲染总预算(编译+HTTP+栅格化) targetWidth: 1600 # 输出宽度(px) maxNodes: 50 # 规模上限(连线 2 倍;超出拒绝渲染并提示模型) tempTtlMinutes: 30 # 临时图保留时长 kroki: endpoint: "http://127.0.0.1:8000" allowPublicEndpoint: false # ⚠️ true=允许 kroki.io 公共服务(图内容将发第三方,强制 HTTPS) connectTimeoutMs: 2000 # 连接/响应头超时 requestTimeoutMs: 12000 # 单请求总超时(覆盖响应体读取全程) maxResponseBytes: 4194304 # SVG 响应上限(流式字节计数) maxConcurrency: 2 circuitBreaker: { enabled: true, failureThreshold: 3, cooldownMs: 30000 } d2: { layout: elk } # dagre | elk(sequence 固定 dagre) imageTag: "" # 部署镜像版本声明(进缓存 key;升级镜像后更新) ``` **使用示例**: ```text 你:用图画一下这个插件的工作流程 Bot:(流程图图片)用户消息 → Yunzai → Agent Loop → 工具调用 → 渲染回复 你:画个时序图看看工具调用过程 Bot:(时序图图片)用户/Agent/工具 三方消息序列 ``` **常见排查**: | 症状 | 原因与处理 | | --- | --- | | 回复「渲染服务不可用」 | Kroki 容器未启动/endpoint 配错:`docker compose -f docs/deploy/kroki-compose.yaml up -d`;或配置 `fallbackRenderer: beautiful-mermaid` 本地回退 | | 连续失败每次都要等很久才回 | 熔断器生效中(连续 3 次失败短路 30s),检查容器 `docker logs agents-kroki` | | 图太大被拒(output_too_large) | 减少 nodes/edges 数量,或调低 `targetWidth` | | 中文显示为方框 | 理论不会发生(内置字体);若手动删除了 `resources/fonts/`,恢复该文件或保留系统 Noto CJK | | 中文流程图正常但主题色不对 | Kroki 镜像版本的 D2 主题编号差异:更新 `kroki.imageTag` 并调整 `model/diagram/themes.js` 后重启 | ### `agent.research` —— 深度研究 🧪早期 > 🧪 **深度研究处于早期开发,效果可能差或不可用**(见顶部「重要提示」)。受搜索源、模型能力、token 消耗影响大,仅作辅助。 | 字段 | 默认 | 说明 | | --- | --- | --- | | `permission` | `master` | `master`(防 token 滥用)/ `all` | | `maxRounds` | `3` | 外层 Supervisor 最大轮次 | | `maxConcurrent` | `3` | 子代理并发上限 | | `workerModel` | 空 | 子代理模型(空则用主模型;省钱可填便宜模型) | | `evaluation` | `true` | 是否跑五维评估 | ### `agent.mcp` —— MCP 服务端 ```yaml mcp: requestTimeout: 60000 servers: fs: # stdio 子进程示例 command: "npx" args: ["-y", "@modelcontextprotocol/server-filesystem", "./"] prefix: "fs" category: "query" # 字符串:该服务端所有工具同类;或按工具映射 { read_file: "query", write_file: "system", default: "query" } remote: # HTTP 远程示例 transport: "http" url: "https://example.com/mcp" headers: { Authorization: "Bearer ..." } listen: false prefix: "rmt" enabled: true ``` > **⚠️ Docker / 精简镜像没有 `npx`?—— MCP 握手超时(ENOENT)** > > 部分 Yunzai Docker 镜像只装了 `node`、**没有 `npm`/`npx`/`corepack`**(某些 `trss`/`miao` 镜像即如此)。此时上面 `command: "npx"` 会启动失败: > ``` > [mcp] xxx 连接失败:传输关闭(进程退出码-2;spawn 失败:ENOENT spawn npx(npx 不在 PATH?…)) > ``` > (旧版本这种情况只甩一句看不懂的 `request timeout: initialize`;现已**立即**报出 ENOENT + 退出码 + stderr 末尾,便于定位。) > > **判断**:`docker exec <容器> command -v npx` —— 输出为空就是容器里没装 npx。 > > **解决方案(任选其一,推荐 ①)**: > > 1. **给容器补上 npm/npx(一次性脚本,推荐)**:仓库自带 [`scripts/bootstrap-npm-docker.sh`](scripts/bootstrap-npm-docker.sh),纯 `node + curl + tar` 实现、不依赖包管理器: > ```bash > docker cp plugins/agents-plugin/scripts/bootstrap-npm-docker.sh <容器>:/tmp/bs.sh > docker exec <容器> sh /tmp/bs.sh > # 装好后 npx 进入容器 PATH,上面 MCP 配置无需任何改动 > ``` > ⚠️ 脚本装在「运行中的容器」里,**容器一旦重建(重新 `docker run`)会丢失**,需重跑;想一劳永逸请把它加进镜像 entrypoint / Dockerfile。 > 2. **改用绝对路径**:若容器别处有 `npx`/`node`,把 `command` 换成绝对路径(如 `/usr/local/bin/npx`)。 > 3. **绕开 npx**:容器内 `npm i -g ` 全局安装后,用 `command: "/usr/bin/node"` + `args: ["<全局模块入口 js 的绝对路径>"]` 直接跑;或改用 `transport: "http"` 连远程 MCP,本地无需任何进程。 ### `agent.tts` —— 语音合成(IndexTTS 2.5 / 豆包 / MiniMax / MiMo) 把文字合成为语音发到聊天(Agent 工具 `tts_speak`)。四家服务商任选其一(`provider` 切换):**IndexTTS 2.5**(本机/内网自托管,音色参考 + 情绪参考/向量)、**豆包**(火山引擎 Seed-TTS,语音指令 / 多情感标签)、**MiniMax**(speech-2.8/2.6/02,9 种情绪标签)、**MiMo**(小米 MiMo-V2.5-TTS,预置音色 + 自然语言风格指令)。**总开关默认关(opt-in)**:需在 Web 面板「语音合成」或配置里显式 `enable: true` 后,`tts_speak` 才会注册、自动语音才生效;云服务商仅在「总开关开 + 选中该服务商 + 密钥/音色齐全」时才会把讲稿发往对应平台。 ```yaml tts: enable: false # 总开关(默认关,opt-in);开启后 tts_speak 才注册、自动语音才生效 provider: indextts # indextts | doubao | minimax | mimo autoReply: true # 开启后每条最终回复自动合成语音(文字/图片照常发,随后追加语音) replyMaxChars: 300 # 自动语音最大字符数(超长按句截断;0=不限) hdVoice: true # 发送前高清化:响度标准化 + 存在感补偿(需宿主 ffmpeg,失败自动回退) judgeModel: "" # 情绪判定模型(四家统一;留空=indextts.model→utilityModel→主模型) judgeTimeoutMs: 300000 # 情绪判定总预算(毫秒,默认 5 分钟,四家统一) indextts: endpoint: "http://127.0.0.1:7860" # IndexTTS 服务地址(Web 面板「语音合成」可测试连接) apiKey: "" # 鉴权网关 API Key(可选,itts_xxx;v1.2 起网关版必填,官方无鉴权留空) lang: ZH voice: "" # 默认音色参考名(在 Web 面板上传参考音频时命名;留空=最新上传) emotionMode: same # same=沿用音色参考情绪 | audio=情绪参考音频 | vector=8 维情绪向量 emotionRef: "" # audio 模式默认情绪参考(可来自其他说话人) emotionWeight: 0.65 # audio 模式情绪影响强度 0~1 autoEmotion: true # vector 模式由 LLM 结合「文本 + 近期对话上下文」自动调节情绪 tier: pro # pro=整段一套情绪 | max=按需拆分逐段情绪 + ffmpeg 合并 segmentGapMs: 300 # max 档段间静音 model: "" # 情绪判定用模型(模型条目 id/模型名;留空=utilityModel→主模型) judgeTimeoutMs: 300000 # 情绪判定单次调用总预算(毫秒,默认 5 分钟;超时中止请求并回退;快失败在预算内重试一次,慢超时不重试) doubao: # 豆包语音合成(火山引擎 Seed-TTS,HTTP Chunked 单向流式) apiKey: "" # 火山引擎 API Key(新版控制台 → API Key 管理,按资源开通「语音合成」) resourceId: seed-tts-2.0 # seed-tts-2.0 | seed-tts-1.0 | seed-tts-1.0-concurr(决定可用音色与计费) speaker: "" # 音色 ID(控制台音色库 voice_type,如 zh_female_vv_uranus_bigtts) model: "" # ""=默认 | seed-tts-2.0-standard | seed-tts-2.0-expressive(语音指令建议 expressive) autoEmotion: true # LLM 判定情绪:2.0 音色→context_texts 语音指令;1.0 音色→emotion 标签 instruct: "" # 固定语音指令(留空=LLM 判定生成,仅 2.0 音色) emotion: "" # 固定情感标签(1.0 多情感音色;LLM 失败/关闭时回退) emotionScale: 0 # 0=按判定强度自动(1~5);手动=固定 emotion_scale speechRate: 0 # 语速 -50~100(100=2 倍速) loudnessRate: 0 # 音量 -50~100(100=2 倍音量) sampleRate: 24000 format: wav # wav | mp3(max 档分段拼接固定 wav) useTagParser: false # 声音复刻 2.0 表现力增强版 Cot 标签解析 tier: pro # pro=整段一次 | max=LLM 分段逐段情绪 + ffmpeg 合并 segmentGapMs: 300 # max 档段间静音(毫秒;0=不留空隙) maxSegmentChars: 140 # max 档单段字符上限(LLM 分段/标点回退,防拆得过碎) minimax: # MiniMax 语音(T2A V2) endpoint: "https://api.minimaxi.com/v1/t2a_v2" # 国际站 https://api.minimax.io/v1/t2a_v2 apiKey: "" # MiniMax API Key(平台 → 接口密钥) groupId: "" # 可选:旧版账号 URL 查询参数 GroupId model: speech-2.8-hd # 2.6/2.8 支持全部 9 种情绪 voiceId: "" # 音色 ID(系统音色或复刻音色,如 male-qn-qingse) autoEmotion: true # LLM 判定 → happy/sad/angry/fearful/disgusted/surprised/calm emotion: "" # 固定情绪标签(回退用) speed: 1.0 # 0.5~2.0 | vol 音量 | pitch 音调 -12~12 sampleRate: 32000 format: wav # wav | mp3 | flac(max 档固定 wav) languageBoost: "" # 语种增强:留空=自动;Chinese/English/Japanese/Arabic/Spanish/auto tier: pro segmentGapMs: 300 # max 档段间静音(毫秒;0=不留空隙) maxSegmentChars: 140 # max 档单段字符上限(LLM 分段/标点回退) mimo: # 小米 MiMo TTS(MiMo-V2.5-TTS,OpenAI 兼容) endpoint: "https://api.xiaomimimo.com/v1" apiKey: "" # MiMo 开放平台 API Key model: mimo-v2.5-tts # mimo-v2.5-tts(预置音色)| mimo-v2.5-tts-voicedesign(文字设计音色,style 必填) voice: mimo_default # 预置音色:mimo_default/冰糖/茉莉/苏打/白桦/Mia/Chloe/Milo/Dean autoEmotion: true # LLM 判定 → 自然语言风格指令(复合情绪/语速/发声方式/导演式)+ 音频标签 style: "" # 固定风格/音色描述指令(留空=LLM 生成;voicedesign 必填;可写"用东北话说""用唱歌的方式") tagMode: auto # 音频标签:auto=句首 (风格) + 行内 [标签](原文保真校验,改写即丢弃)| style=只加句首 | off=不用 format: wav # wav | mp3(max 档固定 wav) tier: pro segmentGapMs: 300 # max 档段间静音(毫秒;0=不留空隙) maxSegmentChars: 140 # max 档单段字符上限(LLM 分段/标点回退) ``` - 配置入口:Web 管理面板 → **语音合成**(服务卡片 → 弹窗配置:接口地址 / API Key / 音色 ID / 测试连接 / 参考音频上传+命名 / 情绪模式与 8 维滑块)。云服务商的「测试连接」会真实合成 2 个字(官方唯一可探活方式,极少计费)。 - **鉴权(可选)**:IndexTTS 服务若套了鉴权网关(v1.2+,官方本体无认证),填 `agent.tts.indextts.apiKey`(`itts_xxx`),请求统一带 `X-API-Key` 头;`401`=Key 缺失/错误、`429`=失败限流、`503`=网关配置故障、`502/504`=上游未就绪,错误信息会直接提示对应处理方式。本插件可直连 `127.0.0.1:7862` 本体(同机部署可绕过网关,key 留空)。 - **自动语音**(`autoReply`,默认开):每条最终回复自动追加语音——文字/图片照常发送,语音内容是正文剥除 markdown/代码/链接/表格/emoji 后的文本(超长按句截断,`replyMaxChars`);合成全过程有 `[tts] 合成开始/完成` 日志。`tts_speak` 工具保留给指定音色/情绪的点播(本轮已点播则不重复补发)。**讲稿清洗在合成入口统一执行**(点播同样生效),破折号(——)会转成停顿而不是被读成"减减"。 - **情绪判定(四家共用一条 LLM 链路)**:由一次旁路 LLM 调用结合文本与近期对话判定 8 维情绪(高兴/愤怒/悲伤/害怕/厌恶/忧郁/惊讶/平静),并可直接产出自然语言风格指令(`style`,支持复合情绪/语速/发声方式/导演式)与音频标签(`tag`/`tagged`)——IndexTTS 直接下发向量;豆包 1.0 → `emotion` 标签 + `emotion_scale`(由向量强度换算);豆包 2.0 → 优先用 LLM `style` 作 `context_texts` 语音指令(无则回退向量模板);MiniMax → 9 标签之一(忧郁→sad);MiMo → LLM `style` 作 user 风格指令 + 按 `tagMode` 组合句首 `(风格)` 与行内 `[标签]`(保真校验)。`judgeModel` 可指定更快/更便宜的小模型,`judgeTimeoutMs` 控制单次判定总预算(默认 5 分钟,单次尝试最多用一半)——快失败(网络/限流等秒级返回)会在剩余预算内自动重试一次;打满单次预算的**慢超时不再重试**(慢模型重试必然再超时,避免白等第二个半预算);判定失败只影响情绪、不影响出语音,日志会给出预算/尝试次数/耗时与"自动判定失败→回退默认"标注便于排查。 - **云服务商接入要点**: - **豆包**([文档](https://docs.volcengine.com/docs/DoubaoVoice/unidirectional-streaming-text-to-speech-http?lang=zh)):HTTP Chunked 单向流式(NDJSON,base64 分片按序拼接,`code 20000000` 结束);新版控制台只需 `X-Api-Key` + 资源版本;`resourceId` 决定可用音色(2.0 音色以 `_uranus_bigtts` 结尾)与计费;语音指令仅 2.0/复刻 2.0 支持(建议 `model: seed-tts-2.0-expressive`)。 - **MiniMax**([文档](https://platform.minimaxi.com/docs/api-reference/speech-t2a-http)):`POST /v1/t2a_v2`(Bearer 鉴权;旧版账号可填 `groupId`),响应 `data.audio` 为 **hex** 编码;情绪仅 `speech-2.6/2.8` 全量支持(`fluent/whisper` 仅 2.6;2.8 不支持 whisper)。 - **MiMo**([文档](https://mimo.mi.com/docs/zh-CN/quick-start/usage-guide/audio/speech-synthesis-v2.5)):OpenAI 兼容 `chat/completions`,朗读文本必须放在 `assistant` 消息、风格指令放 `user` 消息,响应 `choices[0].message.audio.data`(base64);情绪控制已按文档补全——LLM 判定后**直接生成自然语言风格指令**(支持复合情绪"压抑的愤怒/带着哽咽的笑意"、语速与发声方式、导演式角色/场景/指导、唱歌与方言点名),并按 `tagMode` 追加**音频标签**:句首 `(风格)` + 行内 `[笑]/[叹气]/[颤抖]/[语速加快]` 等(插入前后做原文保真校验,任何改写/增删一律丢弃该标签文本);max 档逐段独立风格与标签;`voicedesign` 模型用「固定风格指令」描述音色(不走自动情绪与标签)。 - 三家云服务的 API Key 保存在插件本机 `config/config.yaml`(与 LLM Key 同机制),面板/错误信息会回显配置本身但不会把密钥写入日志;讲稿仅在选中该服务商且配置齐全时才发送到对应平台。 - **高清语音**(`hdVoice`,默认开):发送前经 ffmpeg 做响度标准化(-15 LUFS / 真峰 -1.5dB)+ 存在感补偿(4kHz +5dB、6kHz 高架 +4dB)+ 24kHz 对齐——TTS 输出普遍偏轻偏闷,这一步显著提升清晰度;失败自动回退原始音频(需宿主 ffmpeg)。 - 三种情绪模式:`same` 沿用音色参考的情绪;`audio` 另给一段情绪参考音频(`emotionWeight` 调影响强度);`vector` 保留音色、用 8 维向量控制高兴/愤怒/悲伤/害怕/厌恶/忧郁/惊讶/平静,默认由 LLM 自动调节。 - 档位:`pro` 一次合成(快);`max` LLM 按需拆分、逐段情绪分别合成后用 **ffmpeg** 拼接(更细腻、更耗时,宿主要装 ffmpeg)。 - 何时用语音、各模式怎么选:见技能 [`skills/tts.md`](skills/tts.md)(Agent 按需加载,不占常驻上下文)。 --- ## 🎮 指令 ### 对话 | 指令 | 说明 | | --- | --- | | `@机器人 +内容` | 艾特对话(默认触发) | | `#ai +内容` | 自定义触发词(`trigger=command/both`) | | `#聊天列表` | 查看所有对话(图片) | | `#进入聊天 +id` | 切换对话 | | `#new` | 新建对话 | ### 人设 | 指令 | 说明 | | --- | --- | | `#人设` / `#人设列表` | 查看人设列表(图片) | | `#人设 +id` | 切换人设 | | `#人设详情 +id` | 查看人设内容 | | `#新建人设 +名称 +内容` | 创建自定义人设并切换 | | `#删除人设 +id` | 删除(仅创建者/master) | | `#重置人设` | 恢复默认 | ### 深度研究 🧪 | 指令 | 说明 | | --- | --- | | `#研究 +主题` | 🧪 **早期功能**:深度研究(结果 PDF→高清图→文本),效果可能不稳定 | ### 记忆 / 提醒 | 指令 | 说明 | | --- | --- | | `#记忆` | 查看长期记忆 | | `#忘掉 +关键词` | 按关键词遗忘 | | `#我的提醒` / `#取消提醒 +id` | 提醒管理 | | `#清空所有记录` | 清空**自己**的对话历史/记忆/笔记/提醒/人设绑定(不含配置;2 步确认) | ### 主人指令 | 指令 | 说明 | | --- | --- | | `#模型切换 +id` | 切换 LLM 模型 | | `#启用mcp +名` / `#停止mcp +名` | MCP 服务端启停 | | `#添加mcp +JSON` | 按标准 `mcpServers` JSON 添加 MCP(连接验证+持久化)。**私聊**发 `#添加mcp`(不带 JSON)进入交互式添加:直接粘贴 JSON 即自动测试并应用。如 `{ "mcpServers": { "zai": { "type":"stdio", "command":"npx", "args":[...], "env":{...} } } }` | | `#mcp` | MCP 连接状态 | | `#确认 +id` / `#拒绝 +id` / `#待确认` | 审批待执行危险动作 | | `#agents帮助` / `#agents状态` | 帮助图 / 运行状态 | | `#agents重载` | 热重载配置并立即重建运行时(model/tools/skills/mcp,无需重启框架) | | `#agents更新` / `#agents强制更新` | git pull 拉取最新代码(强制=reset 后 rebase),有代码改动时自动重启 Yunzai 生效 | | `#agents版本` / `#agents更新日志` | 最近提交时间 / 本次更新日志 | --- ## 🧩 扩展开发(工具 / 技能) 本插件支持两种扩展,**详细的开发文档(完整 API 参考 + 示例)已独立到 [开发指南.md](开发指南.md)**: - **工具(Tool)**:给模型新增"动作",模型可直接调用执行。放 `tools/` 目录自动加载,用 `defineToolPack` / `defineTool` / `param` SDK 编写。 - **技能(Skill)**:渐进式披露的"说明书",不新增动作、只教模型"什么场景用哪些工具、按什么顺序"。放 `skills/` 目录自动加载,写 `SKILL.md`。 👉 完整的 SDK API(`defineTool` / `param.*` / `getGroup` / `ok` / `fail`…)、运行时 `ctx` 字段、`meta` 选项(审批 / 串行 / 结果截断)、`category` 与 RBAC、多组完整示例与常见陷阱,见 **[开发指南.md](开发指南.md)**。 ### 🧰 外置工具 / 技能收集仓 社区外置工具与技能集中收集在 **[trss-agent-tools](https://gitee.com/YunXi-67/trss-agent-tools)**([GitHub 镜像](https://github.com/yunhai89/trss-agent-tools)),云崽插件索引库风格、欢迎 PR 提交你的工具/技能: - 把工具包目录整个复制到本插件 `tools/`、技能复制到 `skills/` 即可使用(示例:QQ 音乐 `qqmusic`)。 - 工具包内提供固定模板 `tool.config.js`(`info`:标题/介绍/作者/版本/图标 + 配置 schema);插件运行时自动读取,web 面板「系统 → 外置工具」按 schema 动态渲染,**新增工具无需改前端**。 - 用户配置统一存 `agent.tools.<包名>`,复用配置热加载;运行时用 `getToolConfig('<包名>')` 读取。详见 [开发指南.md](开发指南.md) 与收集仓 [CONTRIBUTING.md](https://gitee.com/YunXi-67/trss-agent-tools/blob/master/CONTRIBUTING.md)。 --- ## 🧠 记忆体系(参考 OpenClaw「文件即真相」) 两层记忆,互补: - **声明式记忆(`MEMORY.md` / `USER.md`)**:Agent 的个人笔记 / 用户画像,**Markdown 文件、人可读可编辑**(位于 `Yunzai/data/agents-plugin/memories/`)。每条一行 `- ` bullet,有字符预算(memory 2200 / user 1375)。模型用 `memory` 工具 add/replace/remove 维护,自动注入 system prompt。旧版 `memory.json`/`user.json` 首次加载自动迁移为 `.md`。可直接编辑文件,重启后生效。 - **召回式记忆(`memory_search` 工具)**:跨会话的长期记忆(偏好/身份/事实/近期事项),相似度×时间衰减召回。**模型主动检索**——回答涉及用户先前说过的偏好、历史决策、待办前,先调 `memory_search(query)` 核实,不要凭印象作答(移植 OpenClaw "Mandatory recall step" 语义)。结果带类型与日期引用。 - **统一用户画像(`agent.profile`)**:把上述散落证据收敛成分面结构(身份/沟通风格/偏好/忌讳/专长/事实),每条带证据、置信、来源(observed/inferred/corrected)与审计链,动态注入且**可纠错、可演进**。隐式风格(消息长短/表情/提问率/活跃时段)由统计推断并标注「(推断)」,样本不足不推断。 - **纠错闭环**:用户明确纠正("不是X,是Y"/"更正:…")时,旧记忆标记 `corrected` 不再召回/注入(保留 `prev` 审计链),更正说法以高置信写入;画像同步按"命中旧说法→整句替换"更新。 - **召回质量**:候选多于要取条数时按 MMR + 每类上限去冗余,避免同义旧事挤满上下文;记录每条记忆的"注入/被引用"使用反馈,反复注入却从未被引用的自动降权。 指令:`#记忆` 查看、`#忘掉 <关键词>` 遗忘;`#画像` 查看用户画像、`#忘记画像 <关键词>` 从画像移除。 --- ## 💻 终端执行(E2B 沙箱 + 全员可用) > **⚠️ 高危**:见上方「安全声明」。`terminal` 默认不注册,需 `agent.sandbox.mode: e2b` + `apiKey` **单独开启**;开启即视为你知晓风险并自担后果。 `terminal` 工具让 Agent 在 **E2B 微虚机**里执行 shell 命令。宿主上**没有任何 shell 执行面**(旧主机执行路径已删除),拿不到沙箱就拒绝执行。 **接入准备**(二选一,详见仓库内 `e2b-infra-nodejs-安全shell接入开发文档.md`): - **E2B 云**:只填 `sandbox.apiKey`(注意:命令与文件会送往第三方)。 - **自托管 Embed**:**仅限有 KVM 的机器**(自家物理机 / 裸金属实例)。腾讯云轻量服务器、普通 CVM/ECS 虚拟机、容器都不行,请用上面的云托管。详见下方「自托管安装」。 > 说明:插件依赖的 `e2b` npm 包只是 **SDK(客户端)**,不含任何沙箱服务端。沙箱由 `e2b-dev/runtime`(Firecracker 基础设施)提供,云托管由 E2B 运营,自托管需自己部署。 ### 🏗️ 自托管安装(E2B Embed) **硬前提(不满足就不要尝试,装了也跑不起来)**: | 项 | 要求 | 为什么 | | --- | --- | --- | | KVM | `/dev/kvm` 存在且可读写 | 每个沙箱是一台 Firecracker microVM,没有硬件虚拟化就无从创建 | | CPU 虚拟化 | `/proc/cpuinfo` 含 `vmx`(Intel)或 `svm`(AMD) | 没暴露虚拟化扩展的客机=嵌套虚拟化未开启,**客机内部无法自行开启** | | 内存 | 宿主可用内存 ≥ 20 GiB(`PF_MIN_FREE_GIB`) | embed 会为沙箱预留大块内存 | | 磁盘 | 空闲 ≥ 30 GiB | 7 个镜像 + Firecracker + 内核 + 模板 | | 系统 | Linux x86-64/arm64,4 KiB 页内核,glibc ≥ 2.34,可写 `/etc` | 官方以 Ubuntu/Debian 验证;不支持 macOS/Windows 宿主与 Container-Optimized OS | > ## ⚠️ 重要:自托管**必须有 KVM**,普通云服务器做不到 > > E2B 的每个沙箱是一台 **Firecracker microVM**,靠 CPU 硬件虚拟化(Intel VT-x / AMD-V)隔离。 > 因此自托管要求机器上真的有 `/dev/kvm`——**普通云服务器(虚拟机)一律没有**: > > | 机器类型 | 能自托管吗 | 原因 | > | --- | --- | --- | > | 自家物理机 / 裸金属服务器 | ✅ 可以(需 BIOS 开 VT-x/AMD-V) | 真机有硬件虚拟化 | > | **腾讯云轻量应用服务器** | ❌ **不行** | 本身是虚拟机,不提供嵌套虚拟化,无 `/dev/kvm` | > | 腾讯云 CVM 标准型 / 阿里云 ECS 共享型·通用型(常见规格) | ❌ 基本不行 | 同上,默认不开嵌套虚拟化(个别规格需工单开通且仍受限) | > | 裸金属实例 / 专属宿主机(腾讯云黑石、阿里云神龙裸金属等) | ✅ 可以 | 直通硬件虚拟化 | > | 明确标注「支持嵌套虚拟化」的实例 | ✅ 可以(需单独开通) | 如 GCE `--enable-nested-virtualization` | > | 各种容器 / Docker 内 / WSL2 | ❌ 不行 | 没有独立的 KVM 设备 | > > **结论:如果你用的是腾讯云轻量服务器(以及绝大多数普通云主机、容器),自托管这条路走不通——请直接用 E2B 云托管**(只填 `agent.sandbox.apiKey`,命令与文件会送往 E2B 云,请自行评估数据敏感度)。 > > 想在云上自托管,只能换到**裸金属 / 专属宿主机**这类有硬件虚拟化的实例。 > > 不确定?在目标机器上跑体检(不改系统):`scripts/install-e2b-selfhost.sh --check`。 > 典型失败输出:`/dev/kvm 不存在` + `CPU 未向本机暴露虚拟化扩展`。 > > 另注:除 KVM 外还需 **可用内存 ≥ 20 GiB / 空闲磁盘 ≥ 30 GiB**——轻量服务器这类小规格即使有 KVM 也不够。 **一键部署脚本**(推荐,内置上述前提检查,不满足会直接拒绝而不是"装一半"): ```bash # ① 只做前提检查(可先在候选机器上跑,不改系统) scripts/install-e2b-selfhost.sh --check # ② 安装(交互式;-y 无人值守;--write-config 装完直接写进插件配置) scripts/install-e2b-selfhost.sh -y --write-config # ③ 卸载(停栈 + 官方 host-teardown 还原宿主参数) scripts/install-e2b-selfhost.sh --uninstall ``` 脚本会:检查前提 → apt 装 docker/compose v2/依赖 → 克隆 `e2b-dev/runtime` 到 `/opt/e2b-runtime` → 执行官方 `host-setup.sh`(hugepages/nbd/sysctl)→ `docker compose up -d --wait` → 跑官方 smoke 自检 → 用控制面 curl 实证创建沙箱 → 导出 `sdk.env` 三要素并给出配置片段(`--write-config` 会备份后直接改写 `config/config.yaml`)。 可调环境变量:`E2B_REF`(锁定 runtime 版本,生产建议锁 CalVer tag)、`E2B_DIR`、`PF_MIN_FREE_GIB`、`MIN_DISK_GIB`、`SKIP_SMOKE`。 **手工步骤**(想自己掌控每一环节时): ```bash sudo apt-get install -y git make docker.io docker-compose-v2 qemu-kvm git clone https://github.com/e2b-dev/runtime.git && cd runtime/embed/compose bash scripts/host-setup.sh # hugepages / nbd / sysctl docker compose up -d --wait docker compose --profile test run --rm smoke # 冒烟:栈内跑官方 JS SDK + 端口连通性 eval "$(docker compose exec ready cat /run/e2b/sdk.env)" # E2B_API_URL / E2B_SANDBOX_URL / E2B_API_KEY ``` 把三要素填进 `agent.sandbox.apiUrl / sandboxUrl / apiKey`: ```yaml agent: sandbox: mode: e2b apiKey: "" apiUrl: "http://:3000" # 控制面 sandboxUrl: "http://:3002" # 数据面(无通配 DNS 时**必须填**,SDK 会自动附路由头) template: base ``` **排障**: | 症状 | 定位 | | --- | --- | | `--check` 报无 `/dev/kvm` | 见上表:换支持 KVM 的机器/实例规格,或改用云托管 | | 控制面 401 / `Unauthorized` | `apiKey` 取错,重读 `/run/e2b/sdk.env` | | `fetch failed` 或连 `:3002` 失败 | `sandboxUrl` 未填或 client-proxy 未起:`docker compose ps` 看服务 | | `TemplateError: You need to update the template` | 模板的 envd 版本过旧,栈内重跑 base 模板构建脚本 | | 沙箱跑到一半消失 | TTL 到期;长任务用续期(插件侧 `sandboxTtlMs` + 半衰续期已内置) | | smoke 失败 | `docker compose logs` 逐个服务看;常见是内存/磁盘不足或内核参数未生效 | 部署完成后验证插件侧链路: ```bash E2B_INTEGRATION=1 node model/sandbox/e2b.integration.test.mjs # 自托管会从插件配置读 apiUrl/sandboxUrl;环境变量优先,便于临时指向别处 ``` **访问控制**: - **全员可用(无身份门槛)**:不再有「terminal 主人」验证码认领。安全边界完全由 E2B microVM 承担:每个会话(群/用户/对话)独占一个沙箱,文件与进程互不可见。 - **无审批、无命令黑名单**:破坏性命令被限制在会话沙箱内(独立 VM/独立 FS/独立网络命名空间),不再靠字符串规则。 - **成本闸**:`maxCommandsPerSession`(单会话命令数上限)、`maxTimeout`(单命令超时)、`maxSandboxes`(全局并发)+ 闲置回收,防任何用户(含被注入诱导的会话)把配额/账单打爆。 **关键配置(`agent.sandbox`)**: | 键 | 默认 | 说明 | | --- | --- | --- | | `mode` | `off` | `off`=terminal 不注册(toolEvo 走本地 fork 档)\| `e2b`=沙箱执行 | | `apiKey` | 空 | E2B 云或自托管团队 key(★敏感,已接入回复脱敏) | | `apiUrl` / `domain` / `sandboxUrl` | 空 | 自托管控制面 / 沙箱域名 / 数据面(client-proxy)地址;云托管留空 | | `template` | `base` | 沙箱模板(CPU/内存/预装依赖由模板承载) | | `maxTimeout` | `600` | 单命令超时上限(秒) | | `defaultCwd` | `/home/user` | 沙箱内默认工作目录(宿主路径在沙箱内无意义) | | `idleMs` / `sandboxTtlMs` | `300000` / `600000` | 闲置回收阈值 / 沙箱 TTL(毫秒,命中时自动续期) | | `maxSandboxes` / `concurrencyWaitMs` | `4` / `15000` | 全局并发上限 / 等名额超时(超时按配额失败) | | `maxCommandsPerSession` | `50` | 单会话命令数上限(0=不限) | | `network.allowOut` / `denyOut` | 包管理器 + `api.openai.com` / 全拒绝 | 出口白名单(**allow 恒优先于 deny**);留空白名单=完全断网 | | `audit` | `true` | 每条命令写审计日志(会话键/退出码/命令前 200 字符,不含密钥) | > 沙箱会话按「群 + 用户 + 会话」绑定:同一会话内文件与进程状态连续(可先装依赖再跑脚本)。群共享模式(`isolation: false`)下同群共用一个沙箱。 ### 🔍 SearXNG(自建免费搜索后端)安装 搜索(`web_search`/`#研究`)若无 Tavily/Exa 等 key,可自建 SearXNG(免费、无 key、隐私)。 > ⚠️ **必须给实例开启 JSON 格式**:SearXNG 默认只输出 HTML,而插件走的是 JSON API。未开启时请求 `format=json` 会被实例拒绝,日志报 `SearXNG HTTP 403`。 ```bash # 1) 写一份启用 json 的 settings(挂载进容器) mkdir -p /opt/searxng cat > /opt/searxng/settings.yml <<'YAML' use_default_settings: true server: secret_key: "change-me-to-a-random-string" limiter: false search: formats: - html - json YAML # 2) 启动 docker run -d --name searxng --restart=always -p 8080:8080 \ -v /opt/searxng/settings.yml:/etc/searxng/settings.yml \ -e SEARXNG_BASE_URL=http://localhost:8080 \ docker.m.daocloud.io/searxng/searxng:latest # 3) 自检:应返回 JSON(不是 403) curl -s "http://localhost:8080/search?q=test&format=json" | head -c 200 ``` > 已有实例补开 json:编辑其 `settings.yml` 的 `search.formats` 加入 `json`,再 `docker restart searxng`(改配置不会热生效)。 配置里填: ```yaml search: searxng: { url: "http://localhost:8080" } ``` > 生产建议给 SearXNG 加 reverse proxy + auth(见 [SearXNG 文档](https://docs.searxng.org))。插件按其 JSON API 调用,无需额外适配。 > 无 key 且未部署 SearXNG 时会回退 DuckDuckGo 抓取;部分网络(如国内)访问不了 DuckDuckGo,此时只能靠 SearXNG 或搜索 API Key。 --- ## 🌐 Stagehand 浏览器自动化(🧪 早期) > 基于 [@browserbasehq/stagehand](https://docs.stagehand.dev) v4。Agent 用自然语言驱动真实浏览器:打开页面、点击、填表、抽取动态渲染后的结构化数据(弥补 web_crawl 不执行 JS 的不足)。 **4 个工具**(`permission=master` 时 `category:'system'` 仅框架主人;`permission=all` 时 `category:'query'` 全员可用,`stagehand__act` 写动作始终需 `#确认`): - `stagehand__goto({url})` — 打开 URL(多步任务起点,页面跨调用保持)。成功返回 `{ok:true, url, title, status?}`(同时提供 `data` 别名) - `stagehand__observe({instruction?})` — 列出可交互元素(只读)。成功返回 `{ok:true, data, metadata?}` - `stagehand__extract({instruction, schema})` — 按自然语言 + JSON Schema 抽结构化数据。成功返回 `{ok:true, data, metadata?}` - `stagehand__act({instruction})` — 点击/输入/提交(写动作,需 `#确认`)。仅 SDK 返回 `data.success===true` 才算成功,返回 `{ok:true, data}` **会话**:按「机器人 + 群/私聊 + 真实操作者 + 对话」隔离懒启动 + 5min idle 自动关;同一会话复用同一页面并**串行**执行 goto/observe/extract/act(不同会话并行),支持"打开 A 站→登录→抓数据"多步任务。限流绑定「机器人 + 真实操作者」,切换对话不重置配额;缺少机器人/用户标识直接拒绝。并发启动前同步预约名额,全局容量含已启动/启动中/关闭中。 **配置**(`agent.stagehand`,默认关): ```yaml stagehand: enable: true mode: local # local(本地 Playwright+chromium,默认) | cloud(Browserbase) headless: true executablePath: "" # 本地 chrome 路径(空=默认/CHROME_PATH;可填复用已装 chrome) browserbaseApiKey: ""# 云模式必填 modelName: "" # Stagehand 原生模型(如 google/gemini-2.5-flash);空=复用插件 provider(仅 OpenAI 兼容);云模式空=自动选 modelApiKey: "" idleTimeoutMs: 300000 maxSessions: 3 opTimeoutMs: 60000 # 单次浏览器操作截止时间(含排队后的执行,超时拒绝迟到结果并清理会话) llmTimeoutMs: 30000 # 单次 LLM 推理截止时间(覆盖请求 + 响应体读取;复用主 provider 代理 fetch) ``` - **LLM**:Stagehand 每次原语调用要一次 LLM 推理。`modelName` 留空时**复用插件已配的 OpenAI 兼容 provider**(deepseek/openai/mimo 等,走 json_schema 结构化输出),并复用主 provider 已配置的代理;插件协议为 anthropic 或想用更强模型,填 `modelName`(五大 provider:openai/anthropic/google/groq/cerebras)。 - **依赖**:`@browserbasehq/stagehand` v4 + `zod-stagehand`(Zod 4 别名,仅 Stagehand extract 用;其余模块仍用根依赖 Zod 3)。`zod-stagehand` 缺失时会回退复用 Stagehand 自带的同版本 Zod 4,因此不会导致插件加载失败;建议仍在云崽根 `pnpm install` 装入插件。本地模式另需 chromium + 系统库(`libnss3 libatk-bridge2.0-dev libgtk-3-dev libxss1 libasound2`)。 - **兼容性影响**:早期版本把 SDK 返回值直接展开到结果根(数组会变成数字键、`result.title` 是原始 SDK 字段);现统一为 `goto` 顶层 `url/title/status`、`observe/extract/act` 的载荷在 `result.data`(`goto` 同时提供 `result.data` 别名)。外部脚本请改读 `result.data`。 - **安全边界**:入口对顶层导航做协议/IP/域名解析校验(含混淆 IPv4、尾点、空 DNS、取消/超时),并在请求级安装 Stagehand DomainPolicy(精确域名 + 子域通配 + IPv4 字面量);IPv6/CIDR/单标签主机无法表达为域名规则,仅入口校验兜底;DNS 重绑定与"子资源访问私有 IP"不被 DomainPolicy 覆盖。因此**不宣称完整 SSRF 出口隔离**。 - 云模式(Browserbase)不在主机跑浏览器、无需本地 chromium,但需 apiKey + 外网。 --- ## 🎭 表情包(LLM 自主附带) 模型在回复中自主判断并内嵌表情包,增强拟人感——模型在文本里写 `[sticker:名称]`,插件在发送层解析替换为对应表情包图片: - **图片模式(默认)**:表情包**内嵌进渲染出的整张回复图片**(文字 + 表情合成一张图)。 - **文本模式**:文本段 + 表情图片段混排发出。 > ℹ️ **表情资源仅来自自动发现**(MaiBot 式):被动采集群内图片 → 视觉判定+打标 → 入库;不再从远端仓库克隆/更新。功能默认关闭;未开启或库为空 → 不注入清单、模型看不到该功能,零影响。 ### 自动发现 开启 `sticker.enable` + `sticker.autoDiscover` 且已配视觉模型(`agent.vision.model`)后,群内图片会被: 1. sha256 去重 → 2. 视觉判定(拒绝照片/普通图片/文档,只收表情包)→ 3. 打标(名称/标签/语义描述)→ 4. 存 `resources/stickers/images/discovered/` 并写入 `index.json`。 入库条目上限 `maxDiscovered`(超限按 `usageCount` 升序淘汰冷门);单张大小上限 `discoverMaxSizeMB`;采集群白名单 `discoverGroups`(空=所有群)。 ### 频率管控(防"每条都带 → 反而更 AI") 四层叠加,保证偶发而非每条都蹦:① **prompt 强约束**(偶尔/严肃场景不用);② **概率闸 `sendRate`**(门控通过后仅按概率真正带图);③ **冷却 `cooldown`**(同会话最小间隔);④ **防连发**(上一条带过则本条不带)。 ### 用法(仅主人) | 指令 | 说明 | | --- | --- | | `#表情包状态` | 总数 / 体积 / 高频 Top5 | | `#表情包开启` / `#表情包关闭` | 热开关 | 关键配置(`agent.sticker`,`enable` 默认关): ```yaml sticker: enable: false # 总开关 sendRate: 0.25 # 概率闸:门控通过后实际带图概率 cooldown: 300 # 同会话两次带图最小间隔(秒) maxPerReply: 2 antiConsecutive: true # 防连发 autoDiscover: false # 自动发现总开关(需 enable + agent.vision.model) discoverGroups: [] # 采集群白名单(空=所有群都采集) maxDiscovered: 200 # 自动发现条目上限 discoverMaxSizeMB: 5 # 单张采集大小上限 MB ``` > **合规**:自动发现只采集群内公开图片,经视觉判定过滤照片/文档;发送侧只发本地 `images/` 内物理存在的文件。 --- ## 🏗️ 架构 ``` apps/ 事件分发与回复编排(agent 对话 / research 研究 / help / render) model/ ├─ render 统一浅色主题 + markdown→图片渲染(marked/highlight.js) ├─ openai · anthropic 协议传输层(流式/重试/熔断/failover) ├─ llm 模型能力注册表 + 熔断器 + 连接池 + embedding ├─ agent ReAct 内核 + 工具/会话/记忆/防护/策略/审批 ├─ prompt 分层 system prompt 构建(执行取向/工具目录/技能/安全) ├─ evolution GEPA 提示词自我进化引擎 ├─ mcp Model Context Protocol 客户端(多服务端) ├─ multiagent 编排器-工人 / pipeline / parallel / router ├─ search · tavily 统一搜索(多源路由 + DDG 兜底) ├─ research 深度研究五阶段管线 + 报告渲染 ├─ media 多模态文件收集/解析/协议转换 ├─ vision 视觉子模型识图 ├─ miyoushe 米游社帖子搜索 ├─ group 群信息 + 群管理工具 ├─ persona 人设库 + 激活绑定 └─ toolkit 工具开发 SDK + 自动加载器 tools/ 自定义工具包(自动加载) skills/ 技能说明书(SKILL.md,自动加载) utils/ Config 配置读写(插件目录 + 热加载) · Log 分级日志 ``` 每个 `model/*` 模块均有离线自检(`node model/<模块>/test.mjs`),合计 **960+ 断言全绿**。 --- ## 🔧 日志与排查 分级日志(`utils/Log.js`):`mark`(里程碑)/ `info`(研究进度)/ `debug`(工具入参·每轮 token)/ `warn` / `error`。开启 `debug: true` 可看到 AI 每次调用工具的名称、入参、结果与每轮 token 用量,深度研究的迭代轮次与搜索词,便于排查。 ### 日志字段说明 一次典型对话会在控制台打出五行 `mark` 日志,各字段含义如下(以实际输出为例): ``` [trigger] user=3891977697 gid=960179589 mode=at inputLen=83 [chat] user=3891977697 gid=960179589 conv=3 model=mimo-v2.5-pro persona=default vision=off thinking=off ctx=1116字 [agent] run start ... inputLen=83 msgs=21 tools=39 maxTurns=50 [agent] run end turns=1 stop=stop usage={in:14816,out:808} replyLen=1098 totalMs=19188 [chat] reply turns=1 stop=stop usage=in:14816/out:808 replyLen=1098 ``` **`[trigger]`** —— 收到消息、判定触发方式时: | 字段 | 含义 | | --- | --- | | `user` | 触发者 QQ | | `gid` | 群号(私聊显示 `-`) | | `mode` | 触发方式:`at`(艾特)/ `cmd`(触发词命令) | | `inputLen` | 用户输入字符数 | **`[chat]`** —— 单轮装配完成、调模型前(本轮上下文快照): | 字段 | 含义 | | --- | --- | | `conv` | 会话 id(`#进入聊天` / `#new` 切换;隔离多轮历史) | | `model` | 当前主模型 id | | `persona` | 当前人设 id(`default` = 内置默认身份) | | `vision` | 主模型视觉能力:`on` = 直发原图 / `off` = 走视觉子模型图转文 | | `thinking` | 模型深度思考(reasoning)开关:`on` = 已启用 `agent.thinking` / `off` = 未启用 | | `ctx` | 注入 system 的「情境感知」文本长度(字):含时间/发言者/运行能力盘点/近期群聊等;为空则不显示 | **`[agent] run start`** —— ReAct 主循环开始: | 字段 | 含义 | | --- | --- | | `msgs` | 发给模型的历史消息条数(会话窗口裁剪后,含本轮 user) | | `tools` | 注册给模型的工具总数(内置 + 自定义 + MCP) | | `maxTurns` | 工具调用轮次预算上限(`agent.maxTurns`,默认 50) | **`[agent] run end` / `[chat] reply`** —— 循环结束 / 回复发出后: | 字段 | 含义 | | --- | --- | | `turns` | 实际执行的模型轮次数(`1` = 一次性回复,未调工具) | | `stop` | 终止原因:`stop`/`end_turn` = 正常回复结束;`clarify` = 澄清短路退出;`max_turns` = 轮次耗尽;`blocked` = 被注入防御拦截 | | `usage` | token 用量:`run end` 的 `{in,out}` 与 `reply` 的 `in:../out:..` 是同一份累计值(多轮累加) | | `replyLen` | 最终回复字符数 | | `totalMs` | 本轮总耗时(毫秒),仅 `run end` 有 | > **排查要点**:`turns` 很大 / `stop=max_turns` → 多步任务卡住或工具反复失败;`usage.in` 持续偏高 → 上下文/记忆膨胀,考虑设 `contextWindow` 开压缩;`ctx` 字数 → 判断情境注入量是否过大。 **MCP 连不上时先看报错措辞**:`request timeout: initialize` = 服务端进程起来了但没在超时内响应握手(npx 首次下载慢 / 网络不通 / 命令错误);`ENOENT spawn npx` / `进程退出码-2` = 容器里压根没有 npx(精简 Docker 镜像常见)—— 解决方案见上文 `agent.mcp` 章节的 ⚠️ 说明;`进程退出码 N` + stderr = 服务端启动即崩溃(缺 API Key / 依赖 / Node 版本,看 stderr 末尾)。 --- ## 🙏 鸣谢 本站在开发过程中参考/借鉴了以下开源项目与研究的思想与实现,谨致谢意: **框架基座** - [TRSS-Yunzai](https://github.com/TimeRainStarSky/Yunzai) —— 插件运行的基座框架 - [Miao-Yunzai](https://github.com/Le-niao/Yunzai-Bot) —— Yunzai 生态前身 - [NapCat](https://github.com/NapNeko/NapCatQQ) —— OneBot 协议端(QQ 对接) **伪人模式(核心参考)** - **[MaiBot](https://github.com/MaiMai-with-u/MaiBot)**(MaiMai-with-u)—— 伪人模式的全程参照:对话关系链与指代消解(回复链解析、被引原文注入、防止认错说话对象)、回复必要性评分体系(强相关分/内容分/压力分/存在感惩罚/指数退避的骨架与参数)、Planner 工具调用式决策(`planner_no_tool_end`、wait 连续上限)、记忆命中作用域白名单(`_is_hit_allowed`:只允许活跃人物命中)、目标消息块防混淆措辞、表情包 `[sticker:名称]` 标记式发送、回复编排(`chat/utils`)。我们在其思路上做了自研增强:Conversation Grounding 层(三对象拆分 + 实体白名单 + 生成校验重生成)、对象纠错识别与情绪冲销、bot↔bot 闭环熔断。 **记忆与记忆体系** - [OpenClaw](https://github.com/openclaw/openclaw) 「文件即真相」记忆设计(`MEMORY.md`/`USER.md` 人可读可编辑 + 主动召回) - MaiBot 心意/记忆架构 —— 伪人独立记忆库的「睡眠整合」三层记忆设计(短时缓冲 → 每日整合 → 遗忘衰减) **管理面板** - [Guoba-Plugin](https://github.com/guoba-yunzai/guoba-plugin) —— 配置热加载与可视化面板思路(本插件自带 Web 面板) **学术研究(GroupWorld × SelfState 设计文档引用)** - Gratch & Marsella — *A Domain-independent Framework for Modeling Emotion* / *EMA: A Process Model of Appraisal Dynamics*(情绪评价理论 OCC/EMA) - Steunebrink et al. — *A Formal Model of Emotions: An Analysis and Formalization of the OCC Model* - Park et al. — [Generative Agents: Interactive Simulacra of Human Behavior](https://github.com/joonspk-research/generative-agents)(记忆流与社会仿真) - Cai et al. — *From Triggers to Emotions: A CPM-Grounded Appraisal Multi-Agent*(情绪触发→评价多智能体) 若列举有遗漏或表述不当,欢迎指正,将及时补充修正。 --- ## 📞 联系 - **QQ 群**:[960179589](https://qm.qq.com/q/960179589) - **作者 QQ**:3891977697 问题反馈、功能建议、工具包分享欢迎进群交流。 ## 许可证 [GPL-3.0](./LICENSE)