name: erispulse-ecosystem description: "适用于:了解生态组件(Dashboard/Cron/AI 模块等)与各平台适配器的接入差异。覆盖场景:ErisPulse 框架本身僅提供核心能力(事件系統、模組系統、配置、路由、日誌等),不內建 GUI、圖片渲染、可視化等「重型」功能。這些能力由社區維護的 第三方模組 提供,按需安裝即可。什麼時候需要閱讀這篇:當你想使用網頁可視化管理機器人(啟停模組、編輯設定、查看日誌、監控事件流),或想為自己的模組註冊一個 Dashboard 管理頁面時閱讀這篇。不需要則跳過。當你的模組需要定時/延時觸發邏輯(定時提醒、週期監控、Cron 表達式調度),且希望任務在框架重啟後不遺失時讀這篇。不需要則跳過。當你想給機器人加 AI 智慧代理能力(工具循環、串流對話、MCP、長期記憶),或想把自己模組的服務暴露給智慧代理呼叫時讀這篇。不需要則跳過。此部分由各适配器開發者維護,用於說明該適配器與 OneBot12 標準的差異和擴展功能。請參考以下各平台的詳細文件:。"
ErisPulse 生态与多平台
This skill is auto-built from the ErisPulse documentation. Repository: https://github.com/ErisPulse/ErisPulse Source paths are annotated per section; see docs/ in the repository for the latest content.
内容大纲
AI 按需读取:只读需要的章节即可,不必全文加载。
- 生态总览: 49-66 行
- 推薦模組: 68-108 行
- 官方客戶端(獨立程式): 110-118 行
- 我也想把自己的模組列在這裡?: 120-128 行
- Dashboard: 130-156 行
- 工作原理: 158-169 行
- 註冊 API: 171-209 行
- 兩種注入模式: 211-244 行
- 側邊欄分組: 246-272 行
- 常用 CSS 類名: 274-309 行
- 認證與 API 調用: 311-333 行
- 完整模組示例: 335-445 行
- 注銷視窗: 447-459 行
- 注意事項: 461-471 行
- 定时任务: 473-493 行
- 功能速覽: 495-502 行
- 快速開始: 504-522 行
- API 概覽: 524-577 行
- 模組卸載時的行為: 579-584 行
- 相關連結: 586-591 行
- AI 对话模块: 593-611 行
- 核心能力: 613-632 行
- 模組擴展: 634-704 行
- 事件訂閱: 706-718 行
- 作為服務被呼叫: 720-726 行
- 介面: 728-736 行
- 平台指南索引: 738-755 行
- 平台特定功能: 757-780 行
- 通用介面: 782-960 行
- 標準格式: 962-1018 行
- 參考連結: 1020-1030 行
- 參與貢獻: 1032-1042 行
生态总览
来源:
docs/zh-TW/ecosystem/README.md(https://github.com/ErisPulse/ErisPulse/blob/main/docs/zh-TW/ecosystem/README.md)
生態模組
ErisPulse 框架本身僅提供核心能力(事件系統、模組系統、配置、路由、日誌等),不內建 GUI、圖片渲染、可視化等「重型」功能。這些能力由社區維護的 第三方模組 提供,按需安裝即可。
Important
本目錄下的文件分為兩類,安裝方式不同:
模組(如 Dashboard / Takumi)使用
epsdk install安裝:epsdk install <模組名>獨立程式(如 ErisPulse-App 客戶端)直接從對應 GitHub Releases 下載安裝,無需
epsdk。
推薦模組
ErisPulse-Dashboard:瀏覽器中的管理面板
機器人掛在伺服器上,啟停模組、改設定、看日誌還得登終端?Dashboard 把這些功能搬到瀏覽器中:模組啟停、設定編輯、日誌查看、事件監控;其他模組還能向側邊欄註冊自訂視窗,管理頁面集中在同一處。
epsdk install Dashboard
文件:Dashboard 使用與視窗註冊 | 項目首頁:PyPI
ErisPulse-Cron:定時任務
要每天定時發簽到提醒、按 Cron 表達式執行週期任務、每隔幾分鐘輪詢一次資料?Cron 提供一次性 / 间隔 / Cron 表達式三種任務類型,回調傳參,SQLite 持久化(重啟不丟任務)。
epsdk install Cron
ErisPulse-QvQChat:通用智能體
想讓群裡有一個會工作的 AI 助手,而不是只會關鍵字回覆?QvQChat 是通用智能體:工具循環覆蓋收發訊息 / 程式碼執行 / 電腦操作 / 生成圖片 / 語音 / MCP / 子智能體,支援流式對話與串行工具回放,內建 Dashboard 視窗。
epsdk install ErisPulse-QvQChat
文件:QvQChat 智能體 | 項目首頁:GitHub
ErisPulse-Takumi:圖片渲染
排行榜、戰報、日程卡這類需要「發圖」的場景,寫個模板渲染成圖片發進群裡即可:支援 HTML / 節點樹 / Jinja / SVG / 動畫(基於 takumi-py),內建中英文字型,開箱即用。
epsdk install Takumi
文件:Takumi 圖片渲染 | 項目首頁:GitHub(作者 @ccd2s)
官方客戶端(獨立程式)
ErisPulse-App:手機上直接跑機器人
沒有常開的伺服器,也想隨時建立實例、安裝模組、查看事件流?ErisPulse-App 是官方全平台客戶端(Android / Windows / Linux / macOS):原生介面建立 / 運行 / 管理多個機器人實例,內建模組商店與事件建構器,手機直接運行,桌面托盤常駐。
所有平台的安裝包均從 GitHub Releases 下載,無需 epsdk。
我也想把自己的模組列在這裡?
歡迎推薦優質的、可被廣泛重用的 ErisPulse 生態模組。要求如下:
- 已發布到 PyPI,且套件名以
ErisPulse-開頭 - 提供基本的 README 與使用範例
- 積極維護,對 Issue 有回應
符合以上條件的模組作者可以透過 PR 在本目錄下新增 <模組名>.md 文件,並在上方推薦列表中補充對應的小節。
Dashboard
来源:
docs/zh-TW/ecosystem/dashboard.md(https://github.com/ErisPulse/ErisPulse/blob/main/docs/zh-TW/ecosystem/dashboard.md)
ErisPulse-Dashboard
Tip
什麼時候需要閱讀這篇:當你想使用網頁可視化管理機器人(啟停模組、編輯設定、查看日誌、監控事件流),或想為自己的模組註冊一個 Dashboard 管理頁面時閱讀這篇。不需要則跳過。
ErisPulse-Dashboard 是 ErisDev 直接維護的 Web 管理面板模組,為 ErisPulse 提供可視化的運行時管理介面:模組啟停、設定編輯、日誌查看、事件流監控等。
Important
Dashboard 不是 ErisPulse 框架的內建功能,需要單獨安裝:
epsdk install Dashboard
Dashboard 還支援其他 ErisPulse 模組將自訂的管理頁面註冊到側邊欄。註冊後,使用者可以直接在 Dashboard 中切換到該模組的專屬視窗頁面,無需額外開發獨立的前端介面。
Note
視窗註冊是可選功能。
- 如果 Dashboard 模組未安裝或未載入,呼叫
sdk.Dashboard.register_view()會拋出異常 - 請務必使用
try/except包裹註冊程式碼,確保模組本身的其他功能不受影響 - 建議在註冊前檢查 Dashboard 是否可用:
hasattr(sdk, 'Dashboard') and sdk.Dashboard
工作原理
模組 on_load()
→ 調用 sdk.Dashboard.register_view(...)
→ Dashboard 後端儲存視窗資訊
→ WebSocket 通知前端
→ 前端動態建立側邊欄導航項目 + 頁面容器
→ 使用者點擊即可查看模組視窗
註冊 API
sdk.Dashboard.register_view(
id="MyModule", # 必填,唯一標識
title="我的模組", # 中文名稱
title_en="My Module", # 英文名稱
icon_svg='<svg>...</svg>', # 側邊欄圖標 SVG
html_content='<div>...</div>', # 頁面 HTML 內容
js_content='function xxx() {}', # 頁面 JavaScript 逻辑
css_content='.my-style {}', # 可選自訂 CSS
iframe_url='', # iframe 模式 URL(與 html_content 二選一)
loader="loadMyModuleView", # 切換到該頁面時調用的 JS 函數名
group="group_extensions", # 側邊欄分組
group_title="", # 自訂分組中文名
group_title_en="", # 自訂分組英文名
)
參數說明
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
id |
str |
是 | 視窗唯一標識,建議使用模組名稱 |
title |
str |
否 | 中文顯示名稱,預設使用 id |
title_en |
str |
否 | 英文顯示名稱,預設使用 title |
icon_svg |
str |
否 | 側邊欄圖標的完整 SVG 字串 |
html_content |
str |
否* | 注入模式的頁面 HTML 內容 |
js_content |
str |
否 | 頁面 JavaScript 代碼 |
css_content |
str |
否 | 頁面自訂 CSS 樣式 |
iframe_url |
str |
否* | iframe 模式的 URL,設置後忽略 html_content |
loader |
str |
否 | 頁面激活時自動調用的 JS 函數名 |
group |
str |
否 | 側邊欄分組標識,預設 group_extensions |
group_title |
str |
否 | 自訂分組的中文標題 |
group_title_en |
str |
否 | 自訂分組的英文標題 |
*
html_content和iframe_url至少提供一個,否則頁面為空白。
兩種注入模式
模式一:HTML/JS 注入(推薦)
直接提供 HTML、JS、CSS 字串,Dashboard 會將內容注入到頁面中。該模式與 Dashboard 樣式完全一致,推薦使用 Dashboard 提供的 CSS 類名。
sdk.Dashboard.register_view(
id="HelloPage",
title="你好頁面", title_en="Hello",
icon_svg='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/></svg>',
html_content='<h1 class="page-title">Hello World</h1><div class="card"><div class="card-body">這是一個示例頁面</div></div>',
group="group_tools",
)
完整的天氣模組示例(包含 API 路由、JS 互動等)請見下方 完整模組示例。
模式二:iframe 嵌入
模組提供自己的 HTML 頁面 URL(需自行註冊路由),Dashboard 以 iframe 方式嵌入。適合需要完全獨立 UI 或複雜互動的場景。
sdk.Dashboard.register_view(
id="MyVisualizer",
title="數據可視化", title_en="Data Visualizer",
iframe_url="/MyVisualizer/view",
group="group_tools",
)
iframe 模式會自動在 URL 後追加
token參數用於認證。
側邊欄分組
模組可指定視窗所在的側邊欄分組。Dashboard 內建以下分組:
| 分組標識 | 中文名 | 位置 |
|---|---|---|
group_overview |
概覽 | 第1組 |
group_events |
事件 | 第2組 |
group_extensions |
扩展 | 第3組(預設) |
group_system |
系統 | 第4組 |
group_tools |
工具 | 第5組 |
指定內建分組名,模組視窗會追加到該分組末尾:
group="group_tools" # 追加到"工具"分組
也可以使用自訂分組名(不以 group_ 開頭),Dashboard 會自動創建新分組:
group="my_group",
group_title="我的分組",
group_title_en="My Group",
常用 CSS 類名
模組視窗使用 HTML 注入模式時,可直接使用 Dashboard 已有的 CSS 類名來保持視覺一致性:
| 類名 | 用途 |
|---|---|
page-title |
頁面標題,如 <h1 class="page-title">標題</h1> |
card |
卡片容器 |
card-header |
卡片標題欄 |
card-body |
卡片內容區域 |
grid-2 |
兩列網格佈局 |
grid-3 |
三列網格佈局 |
btn |
基礎按鈕 |
btn-primary |
主按鈕(藍色) |
btn-secondary |
次要按鈕 |
btn-icon |
圖標按鈕 |
btn-danger |
危險操作按鈕 |
Dashboard 使用 CSS 變數控制主題色,你可以在模組視窗中直接引用:
| CSS 變數 | 用途 |
|---|---|
var(--bg-p) |
主背景色 |
var(--bg-s) |
次背景色 |
var(--bg-t) |
三級背景色(卡片等) |
var(--tx-p) |
主文字色 |
var(--tx-s) |
次文字色 |
var(--tx-t) |
輔助文字色 |
var(--bd) |
邊框色 |
var(--accent) |
強調色 |
var(--ok-c) |
成功色 |
var(--er-c) |
錯誤色 |
這些變數會根據 Dashboard 的亮色/暗色主題自動切換,模組無需額外處理。
認證與 API 調用
在模組視窗的 JS 中調用模組自己的 API 時,需要攜帶 Dashboard 的 Token 進行認證:
var token = localStorage.getItem('__ep_tk__');
var resp = await fetch('/YourModule/api/data', {
headers: { 'Authorization': 'Bearer ' + token }
});
var data = await resp.json();
模組的 API 端點可以自行決定是否驗證 Token。如果需要驗證,可從請求頭中提取:
async def _api_data(self, request):
token = request.headers.get("Authorization", "").replace("Bearer ", "")
if not token:
return {"error": "Unauthorized"}, 401
return {"data": "hello"}
完整模組示例
以下是一個完整的天氣模組示例,展示如何註冊視窗、提供 API 數據、以及在卸載時清理資源:
from ErisPulse import sdk
from ErisPulse.Core.Bases import BaseModule
from ErisPulse.Core.Event import command
class Main(BaseModule):
def __init__(self):
self.sdk = sdk
self.logger = sdk.logger.get_child("Weather")
self.config = self._load_config()
@staticmethod
def get_load_strategy():
from ErisPulse.loaders import ModuleLoadStrategy
return ModuleLoadStrategy(lazy_load=False, priority=50)
async def on_load(self, event):
self._register_routes()
self._register_dashboard_view()
self.logger.info("天氣模組已載入")
async def on_unload(self, event):
self._unregister_routes()
if hasattr(self.sdk, 'Dashboard') and self.sdk.Dashboard:
self.sdk.Dashboard.unregister_view("Weather")
self.logger.info("天氣模組已卸載")
def _load_config(self):
config = self.sdk.config.getConfig("Weather")
if not config:
default = {"city": "北京", "api_key": ""}
self.sdk.config.setConfig("Weather", default)
return default
return config
def _register_routes(self):
r = self.sdk.router
r.register_http_route("Weather", "/api/current",
handler=self._api_current, methods=["GET"])
def _unregister_routes(self):
r = self.sdk.router
try:
r.unregister_http_route("Weather", "/api/current")
except Exception:
pass
async def _api_current(self, request):
return {
"city": self.config.get("city", "北京"),
"temp": 25,
"humidity": 60,
}
def _register_dashboard_view(self):
try:
dashboard = self.sdk.Dashboard
dashboard.register_view(
id="Weather",
title="天氣", title_en="Weather",
icon_svg='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>',
html_content='''
<h1 class="page-title">天氣查詢</h1>
<p style="color:var(--tx-s);margin-bottom:16px">查看當前天氣資訊</p>
<div class="grid-2">
<div class="card">
<div class="card-header">當前天氣</div>
<div class="card-body">
<div id="weather-info" style="font-size:14px;color:var(--tx-s)">點擊刷新加載</div>
</div>
</div>
<div class="card">
<div class="card-header">操作</div>
<div class="card-body">
<button class="btn btn-primary" onclick="refreshWeather()">刷新</button>
</div>
</div>
</div>
''',
js_content='''
async function loadWeatherView() { await refreshWeather(); }
async function refreshWeather() {
var el = document.getElementById('weather-info');
if (!el) return;
el.textContent = '加載中...';
try {
var resp = await fetch('/Weather/api/current', {
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('__ep_tk__') }
});
var data = await resp.json();
el.innerHTML = '<p>城市: ' + (data.city || '--') + '</p>' +
'<p>溫度: ' + (data.temp || '--') + '°C</p>' +
'<p>濕度: ' + (data.humidity || '--') + '%</p>';
} catch (e) {
el.textContent = '加載失敗: ' + e.message;
}
}
''',
loader="loadWeatherView",
group="group_tools",
)
except Exception as e:
self.logger.warning(f"註冊 Dashboard 視窗失敗: {e}")
注銷視窗
模組卸載時應呼叫 unregister_view() 清理已註冊的視窗:
async def on_unload(self, event):
if hasattr(self.sdk, 'Dashboard') and self.sdk.Dashboard:
self.sdk.Dashboard.unregister_view("Weather")
註銷後 Dashboard 前端會透過 WebSocket 實時移除側邊欄導航項目和頁面內容,無需使用者刷新。
注意事項
- 載入順序 — Dashboard 的載入優先級為
99999(高優先級),你的模組優先級應低於此值(如50),確保 Dashboard 先載入完成 - 防禦性編程 — 註冊視窗時使用
try/except包裹,因為 Dashboard 模組可能未安裝或未載入 - 資源清理 — 在
on_unload中呼叫unregister_view()移除已註冊的視窗 - ID 唯一性 —
id參數在整個 Dashboard 中必須唯一,建議直接使用模組名稱 - SVG 圖標 —
icon_svg應為完整的<svg>標籤,建議尺寸使用viewBox="0 0 24 24",使用stroke="currentColor"繼承 Dashboard 主題色 - JS 函數命名 —
js_content中的函數名應具有唯一性(如loadWeatherView),避免與其他模組衝突 - 動態更新 — 模組註冊/註銷視窗後,Dashboard 前端會透過 WebSocket 實時更新側邊欄,無需刷新頁面
定时任务
来源:
docs/zh-TW/ecosystem/cron.md(https://github.com/ErisPulse/ErisPulse/blob/main/docs/zh-TW/ecosystem/cron.md)
ErisPulse-Cron
Tip
什麼時候需要讀這篇:當你的模組需要定時/延時觸發邏輯(定時提醒、週期監控、Cron 表達式調度),且希望任務在框架重啟後不遺失時讀這篇。不需要則跳過。
ErisPulse-Cron 是 ErisPulse 生態的定時任務調度模組,為其他模組提供統一的定時任務 API:支援一次性定時、間隔循環、Cron 表達式三種任務類型,回呼傳參,SQLite 持久化(重啟不丟任務)。
Important
Cron 不是 ErisPulse 框架的內建功能,需要單獨安裝:
epsdk install Cron
安裝後透過 sdk.Cron 存取全部介面。
功能速覽
- 三種定時類型:一次性(
once)、間隔循環(interval)、Cron 表達式(cron) - 回調傳參:建立時傳入
callback_data,觸發時原樣返回,方便識別任務來源 - 持久化:任務儲存在 SQLite(經
sdk.storage),框架重啟後自動恢復 - 錯過策略:立即觸發 / 跳過 / 重新排程,可按任務選擇
- 任務管理:暫停、恢復、取消、手動觸發、清理過期任務
- Dashboard 集成:已安裝 ErisPulse-Dashboard 時自動註冊管理視窗
快速開始
from ErisPulse import sdk
# 1. 註冊回調處理器
@sdk.Cron.on_trigger
async def handle_trigger(info):
data = info["callback_data"]
print(f"任務觸發: {info['task_id']}, 數據: {data}")
# 2. 創建定時任務
task_id = sdk.Cron.once(
delay=60,
callback_data={"type": "reminder", "msg": "該喝水了"},
)
API 概覽
創建任務
# 一次性:延遲 600 秒觸發
sdk.Cron.once(delay=600, callback_data={"order_id": "123"}, label="訂單超時提醒")
# 間隔循環:每 300 秒觸發,最多 100 次
sdk.Cron.interval(interval_seconds=300, callback_data={"monitor": "server-1"}, max_runs=100)
# Cron 表達式:工作日每天 9:30
sdk.Cron.cron(expression="30 9 * * 1-5", callback_data={"type": "daily_report"})
# 通用可選參數:trigger_at(絕對時間戳)、delay(首次延遲)、timezone、
# max_runs(0=無限)、label、source(創建者模組名)、missed_policy(錯過策略)
常用 Cron 表達式:*/5 * * * *(每 5 分鐘)、0 8 * * *(每天早 8 點)、30 9 * * 1-5(工作日 9:30)、0 0 1 * *(每月 1 號)。
回調
@sdk.Cron.on_trigger
async def my_handler(info):
# info 含 task_id / task_type / callback_data / label / source /
# run_count / max_runs / created_at / last_run / trigger_time
...
支援註冊多個 handler,全部依次調用,單個 handler 異常不會影響其他 handler。
管理任務
sdk.Cron.cancel(task_id) # 取消
sdk.Cron.pause(task_id) # 暫停
sdk.Cron.resume(task_id) # 恢復(reschedule=True 重新計算下次觸發)
await sdk.Cron.trigger_now(task_id) # 手動立即觸發(不影響原計劃)
sdk.Cron.get_task(task_id) # 查看單個任務
sdk.Cron.list_tasks(source="MyModule") # 列出任務(支援 source/status/task_type 過濾)
sdk.Cron.delete_task(task_id) # 刪除任務記錄
sdk.Cron.cleanup() # 清理 7 天前的已完成/已取消任務
錯過策略(missed_policy)
框架重啟後,對於錯過觸發時間的任務:
| 策略 | 行為 |
|---|---|
fire_immediately |
立即觸發(預設) |
skip |
跳過本次,等下次 |
reschedule |
從當前時間重新計算下次觸發 |
模組卸載時的行為
Cron 的任務資料是持久化資產:任務創建方模組被卸載或停用不會刪除已建立的任務。但該模組註冊的回呼句柄會被清除——基於歸屬權系統的外部清理鉤子,Cron 在替其他模組托管回呼時會自動記名,當對方模組被卸載/停用時會自動拋棄其回呼句柄,確保對方模組實例可以被正常回收。
- 任務創建方重新載入後重新
on_trigger即恢復接收觸發 - 不再需要的任務可用
sdk.Cron.cancel(task_id)/delete_task(task_id)清理
相關連結
AI 对话模块
来源:
docs/zh-TW/ecosystem/qvqchat.md(https://github.com/ErisPulse/ErisPulse/blob/main/docs/zh-TW/ecosystem/qvqchat.md)
ErisPulse-QvQChat 通用智慧代理
Tip
什麼時候需要讀這篇:當你想給機器人加 AI 智慧代理能力(工具循環、串流對話、MCP、長期記憶),或想把自己模組的服務暴露給智慧代理呼叫時讀這篇。不需要則跳過。
ErisPulse-QvQChat 是一個 通用智慧代理模組,圍繞工具循環建構:收發訊息、呼叫生態模組服務、編寫並執行程式碼、操作電腦、生成圖片語音、管理排程任務與長期記憶——全部透過同一套工具協定完成。
Important
QvQChat 需要單獨安裝:
epsdk install ErisPulse-QvQChat
同時需要在「模型池」新增至少一個 OpenAI 相容模型(Base URL、API Key、模型名稱)。
核心能力
| 能力 | 說明 |
|---|---|
| 工具循環 | 模型輸出工具呼叫 → 並行執行 → 結果回填 → 繼續推理,直到給出最終回答 |
| 串流對話 | SSE 逐字輸出,工具步驟即時可見;重新整理 / 切走再回來,進度不丟 |
| 上下文壓縮 | 超過 token 閾值自動把舊對話壓縮為摘要(預設 128000 估算,可自訂) |
| 生態服務橋 | 自動發現模組宣告的服務並轉為工具,裝卸模組即增減能力 |
| MCP 用戶端 | stdio 與 Streamable HTTP,MCP 工具併入同一工具集 |
| 子智慧代理 | spawn_agent 派出獨立會話的子智慧代理探索任務,只回報結論 |
| 行程內執行 | run_python_sdk 主行程內執行 Python,直接存取執行時物件 |
| 電腦操作 | 三級安全沙箱(strict / standard / permissive),危險操作確認,全程稽核 |
| 視覺理解 | 圖片自動注入模型(不支援圖片時自動剝離重試) |
| 附件 | 任意檔案依 hash 去重後寫入磁碟,路徑交給 AI 自行處理;Ctrl+V 貼上截圖 |
| 分享會話 | 臨時唯讀連結(有效期 + token 預算),匯出 Markdown |
| 排程任務 | cron / 一次性 / 間隔,持久化,權限隨建立者 |
| 會話接管 | 管理員可讓智慧代理獨佔一個會話 |
| 人格系統 | 系統提示詞 + 開場對話 + 工具白名單,可按會話綁定 |
| 長期記憶 | 每會話記憶條目,按相似度檢索注入 |
| AI 自動命名 | 會話首輪回覆後自動生成簡短標題 |
模組擴展
任何 ErisPulse 模組宣告 services 即自動成為 QvQChat 的工具,無需專門介面:
from ErisPulse.Core.Bases import BaseModule, ModuleMeta
class Main(BaseModule):
@staticmethod
def get_meta() -> ModuleMeta:
return ModuleMeta(name="Draw", services=[
{"name": "draw", "description": "根據描述生成圖片,回傳圖片 URL"},
])
async def draw(self, prompt: str, size: str = "1024x1024"):
return {"image_url": "https://..."}
服務的方法簽名自動對映為工具的 JSON Schema 參數定義,docstring 首行作為參數說明。
深度整合(可選)
模組可以額外實作以下任意服務,每個服務獨立可選——一個模組可以只做人格擴展,也可以只注入提示詞:
qvq_prompts() → 注入系統提示詞
回傳 list[str] 或 list[{"text": str, "priority": int}],依 priority 升冪拼接。
async def qvq_prompts(self):
return [
{"text": "畫圖後用 send_message 把圖片發給使用者。", "priority": 10},
{"text": "支援的風格:動漫、寫實、水彩、像素。", "priority": 20},
]
qvq_personas() → 註冊人格預設
回傳人格清單,id 自動加 ext.<模組名>. 前綴,模組卸載自動清理。適合專門提供人格擴展的模組(如情感陪伴、翻譯專員、程式碼審查員等)。
async def qvq_personas(self):
return [
{"id": "companion", "name": "暖男", "system": "你是一個溫暖體貼的聊天夥伴..."},
{"id": "coder", "name": "程式碼導師", "system": "...", "tools": ["read_file", "run_python"]},
]
tools 可選限定該人格可用的工具子集。
qvq_schemas() → 顯式參數 schema
回傳 dict[服務名, JSON Schema],覆寫方法簽名推斷。參數複雜或需要嚴格驗證時使用。
async def qvq_schemas(self):
return {
"draw": {
"type": "object",
"properties": {
"prompt": {"type": "string", "description": "畫面描述"},
"size": {"type": "string", "enum": ["512x512", "1024x1024"]},
},
"required": ["prompt"],
},
}
重新整理時機
深度整合服務的重新整理時機:啟動、模組裝卸、Dashboard「工具」頁手動重新整理。
事件訂閱
QvQChat 廣播兩個生命週期事件:
| 事件 | 時機 | 負載 |
|---|---|---|
qvq.message |
收到使用者訊息 | chat_key platform sender_id sender_name text is_group |
qvq.replied |
回覆發出後 | chat_key reply tools |
async def setup(self):
sdk.lifecycle.on("qvq.message", self.on_message)
作為服務被呼叫
| 服務 | 簽名 | 說明 |
|---|---|---|
chat |
(session_id, prompt, persona="") |
與智慧代理對話,回傳文字 |
run_prompt |
(chat_key, prompt, ...) |
執行提示詞,結果可傳送到目標會話 |
get_status |
() |
執行狀態摘要 |
介面
透過 /QvQChat/view 獨立存取,或嵌入 Dashboard 側邊欄。


平台指南索引
来源:
docs/zh-TW/platform-guide/README.md(https://github.com/ErisPulse/ErisPulse/blob/main/docs/zh-TW/platform-guide/README.md)
ErisPulse PlatformFeatures 文件
基線協議:OneBot12
本文檔為平台特定功能指南,包含:
- 各適配器支援的Send方法鏈式呼叫範例
- 平台特有的事件/訊息格式說明
通用使用方法請參考:
平台特定功能
此部分由各适配器開發者維護,用於說明該適配器與 OneBot12 標準的差異和擴展功能。請參考以下各平台的詳細文件:
此外還有
sandbox適配器,但此適配器無需維護平台特性文件
通用介面
Send 鏈式呼叫
所有適配器都支援以下標準呼叫方式:
注意: 文件中的
{AdapterName}需替換為實際適配器名稱(如yunhu、telegram、onebot11、
- 指定類型和ID:
To(type,id).Func()# 獲取適配器實例 my_adapter = adapter.get("{AdapterName}") # 發送訊息 await my_adapter.Send.To("user", "U1001").Text("Hello") # 例如: yunhu = adapter.get("yunhu") await yunhu.Send.To("user", "U1001").Text("Hello") - 僅指定ID:
To(id).Func()my_adapter = adapter.get("{AdapterName}") await my_adapter.Send.To("U1001").Text("Hello") # 例如: telegram = adapter.get("telegram") await telegram.Send.To("U1001").Text("Hello") - 指定發送帳號:
Using(account_id)my_adapter = adapter.get("{AdapterName}") await my_adapter.Send.Using("bot1").To("U1001").Text("Hello") # 例如: onebot11 = adapter.get("onebot11") await onebot11.Send.Using("bot1").To("U1001").Text("Hello") - 直接呼叫:
Func()my_adapter = adapter.get("{AdapterName}") await my_adapter.Send.Text("廣播訊息") # 例如: email = adapter.get("email") await email.Send.Text("廣播訊息")
異步發送與結果處理
Send DSL 的方法返回 asyncio.Task 對象,這意味著您可以選擇是否立即等待結果:
# 獲取適配器實例
my_adapter = adapter.get("{AdapterName}")
# 不等待結果,訊息在背景發送
task = my_adapter.Send.To("user", "123").Text("Hello")
# 如果需要獲取發送結果,稍後可以等待
result = await task
發送規則裝飾器
在實際開發中,經常需要:發送成功後才執行後續邏輯、失敗自動重試、超時取消、發送進度監控等。Send DSL 內建了一套發送規則裝飾器,透過鏈式方法附加規則:
| 方法 | 說明 |
|---|---|
.Hook(callback) |
發送成功後執行的回調(可多次呼叫) |
.Retry(times=1) |
失敗自動重試 N 次(含首次共 N+1 次) |
.Timeout(seconds) |
單次發送超時,超時取消(可與 Retry 叠加) |
.Defer(seconds) |
延遲發送(進程內定時,不持久化) |
.OnProgress(callback) |
各階段進度回調,傳入 SendContext |
.OnError(callback) |
最終失敗時的錯誤回調(僅觸發一次) |
yunhu = adapter.get("yunhu")
# 發送成功後才扣積分
await (yunhu.Send.To("user", "123")
.Hook(lambda r: deduct_points("123"))
.Text("消費成功"))
# 失敗重試 + 超時取消 + 進度監控
def on_progress(ctx):
print(f"階段: {ctx.stage}, 嘗試: {ctx.attempt + 1}/{ctx.max_attempts}")
task = (yunhu.Send.To("user", "123")
.Retry(3) # 最多重試 3 次
.Timeout(10) # 每次超時 10 秒
.OnProgress(on_progress)
.OnError(lambda ctx: notify_admin(ctx.error))
.Text("重要通知"))
規則方法返回 self,必須放在發送方法(Text/Image 等)之前呼叫。SendContext 包含 stage(pending/sending/retrying/success/failed/timeout)、attempt、elapsed、error、result 等欄位,便於監控。
批量建構模式(Build)
一條鏈路中建構多個發送方法,最後統一執行。適用於「一口氣發多條訊息」的場景:
yunhu = adapter.get("yunhu")
# 建構多條訊息,統一發送
results = await (yunhu.Send.To("user", "123")
.Build() # 進入建構模式
.Text("通知一")
.Image("pic.jpg")
.Text("通知二")
.send_all()) # 統一執行
# results = [Text結果, Image結果, Text結果]
.send_all() 默認並行執行(併發發送,效率高)。需要保證訊息到達順序時呼叫 .Sequential() 串行執行:
# 串行執行(保證順序)+ 失敗重試
await (yunhu.Send.To("group", "456")
.Build()
.Sequential() # 按順序依次發送
.Retry(2) # 失敗的條目各自重試
.Text("第一條").Text("第二條")
.send_all())
批量執行採用失敗繼續策略:某條失敗不會中斷其他條,失敗的條目自動重試。批量也支援整批的 Hook(全部成功後觸發)、OnError(有失敗時觸發)、OnProgress(進度回調)。
更詳細的規則與批量建構說明請參考 SendDSL 詳解。
事件監聽
有三種事件監聽方式:
平台原生事件監聽:
from ErisPulse.Core import adapter, logger @adapter.on("event_type", raw=True, platform="{AdapterName}") async def handler(data): logger.info(f"收到{AdapterName}原生事件: {data}")OneBot12標準事件監聽:
from ErisPulse.Core import adapter, logger # 監聽OneBot12標準事件 @adapter.on("event_type") async def handler(data): logger.info(f"收到標準事件: {data}") # 監聽特定平台的標準事件 @adapter.on("event_type", platform="{AdapterName}") async def handler(data): logger.info(f"收到{AdapterName}標準事件: {data}")Event模組監聽:
Event的事件基於adapter.on()函數,因此Event提供的事件格式是一個OneBot12標準事件from ErisPulse.Core.Event import message, notice, request, command message.on_message()(message_handler) notice.on_notice()(notice_handler) request.on_request()(request_handler) command("hello", help="發送問候訊息", usage="hello")(command_handler) async def message_handler(event): logger.info(f"收到訊息: {event}") async def notice_handler(event): logger.info(f"收到通知: {event}") async def request_handler(event): logger.info(f"收到請求: {event}") async def command_handler(event): logger.info(f"收到命令: {event}")
其中,最推薦的是使用 Event 模組進行事件處理,因為 Event 模組提供了豐富的事件類型,以及豐富的事件處理方法。
標準格式
為方便參考,這裡給出了簡單的事件格式,如果需要詳細資訊,請參考上方的連結。
注意: 以下格式為基礎 OneBot12 標準格式,各適配器可能在此基礎上有擴展欄位。具體請參考各適配器的特定功能說明。
標準事件格式
所有適配器必須實現的事件轉換格式:
{
"id": "event_123",
"time": 1752241220,
"type": "message",
"detail_type": "group",
"platform": "example_platform",
"self": {"platform": "example_platform", "user_id": "bot_123"},
"message_id": "msg_abc",
"message": [
{"type": "text", "data": {"text": "你好"}}
],
"alt_message": "你好",
"user_id": "user_456",
"user_nickname": "ExampleUser",
"group_id": "group_789"
}
標準回應格式
消息發送成功
{
"status": "ok",
"retcode": 0,
"data": {
"message_id": "1234",
"time": 1632847927.599013
},
"message_id": "1234",
"message": "",
"echo": "1234",
"{platform}_raw": {...}
}
消息發送失敗
{
"status": "failed",
"retcode": 10003,
"data": null,
"message_id": "",
"message": "缺少必要參數",
"echo": "1234",
"{platform}_raw": {...}
}
參考連結
ErisPulse 項目:
相關官方文件:
參與貢獻
我們歡迎更多開發者參與編寫和維護適配器文件!請按照以下步驟提交貢獻:
- Fork ErisPuls 倉庫。
- 在
docs/platform-features/目錄下建立一個 Markdown 檔案,並以<平台名稱>.md命名。 - 在本
README.md檔案中新增您貢獻的適配器連結以及相關官方文件。 - 提交 Pull Request。
感謝您的支持!