跳到主要内容

🔔 Events:在 OPL 数据空间中使用 __event_emitter____event_call__

OPL 数据空间的插件体系不只是“接收输入再输出结果”。它还支持与 UI 和用户进行实时、交互式通信。为此, OPL 数据空间提供了 __event_emitter____event_call__ 两个内建助手。

本页说明:

  • 什么是事件
  • 如何在 Tool / Function / Pipe 中触发事件
  • 有哪些内建事件类型可用

什么是事件

事件就是从后端代码发往 Web UI 的实时通知或交互请求。它可以用来:

  • 更新聊天中的状态
  • 显示通知
  • 请求用户确认
  • 弹出输入框
  • 注入文件或嵌入内容

可以把它理解成:你的插件可以主动触发 toast、状态条、模态框,甚至驱动一小段 UI 流程。

可用范围

原生 Python Tools / Functions

在 OPL 数据空间内部直接定义的 Python Tool 和 Function,可以完整使用 __event_emitter____event_call__

外部工具(OpenAPI / MCP)

外部工具也可以通过专用 REST 端点把事件发回 UI。若启用了 ENABLE_FORWARD_USER_INFO_HEADERS=True, OPL 数据空间会在外部工具请求中附带:

Header含义
X-Open-WebUI-Chat-Id当前工具调用所属的聊天 ID
X-Open-WebUI-Message-Id当前工具调用关联的消息 ID

外部工具可以据此向:

POST /api/v1/chats/{chat_id}/messages/{message_id}/event

发送事件。

外部工具事件

对于 OpenAPI / MCP 这类外部工具,推荐把聊天 ID 与消息 ID 从请求头中取出,然后调用上面的 /event 端点把事件回推到当前会话。这样外部工具也可以像原生 Tool 一样更新状态、发通知或请求用户输入。

基本用法

发送单向事件

await __event_emitter__(
    {
        "type": "status",
        "data": {
            "description": "Processing started!",
            "done": False,
            "hidden": False,
        },
    }
)

你不需要自己填 chat_idmessage_id; OPL 数据空间会自动处理路由。

发送交互事件

需要等用户响应时,使用 __event_call__

result = await __event_call__(
    {
        "type": "input",
        "data": {
            "title": "Please enter your password",
            "message": "Password is required for this action",
            "placeholder": "Your password here",
        },
    }
)

返回值就是用户的输入或操作结果。

可配置超时

__event_call__ 默认最多等待 300 秒。超时可通过 WEBSOCKET_EVENT_CALLER_TIMEOUT 调整。

事件载荷结构

{
  "type": "event_type",
  "data": { ... }
}

通常只需要关心 typedata 两个字段。

事件类型总览

type用途典型 payload
status显示状态/进度{description, done, hidden}
chat:completion提供一次 completion 结果内部高级用法
chat:message:delta, message向当前消息追加文本{content: "..."}
chat:message, replace替换当前消息全文{content: "..."}
chat:message:files, files设置或覆盖消息文件{files: [...]}
chat:title更新会话标题{title: "..."}
chat:tags更新聊天标签tag 数组或对象
source, citation添加来源或引用结构化来源数据
notification显示 toast 通知{type, content}
confirmation请求确认{title, message}
input请求输入{title, message, placeholder, value?, type?}
execute在浏览器端执行 JS{code: "..."}
chat:message:favorite更新收藏/置顶状态{"favorite": bool}

关键事件说明

status

最适合做进度反馈:

await __event_emitter__(
    {
        "type": "status",
        "data": {
            "description": "Step 1/3: Fetching data...",
            "done": False,
            "hidden": False,
        },
    }
)

done

done 决定前端状态文本是否保持 shimmer/loading 动画:

done前端效果
false显示加载动效
true静态显示,表示此阶段完成
一定要发一个最终 done: true

如果你用了 status,最后至少要发一次 done: true。否则最后那条状态会一直保持“还在处理”的视觉效果。

hidden

hidden: true 时,状态会写入 statusHistory,但不会显示在当前状态条中。适合内部状态记录或不想暴露给用户的过程信息。

chat:message:delta / message

用于向当前消息追加内容:

await __event_emitter__(
    {
        "type": "chat:message:delta",
        "data": {"content": "Partial text, "}
    }
)

chat:message / replace

用于整体替换当前消息正文:

await __event_emitter__(
    {
        "type": "chat:message",
        "data": {"content": "Final, complete response."}
    }
)

files

为消息附加文件或覆盖文件列表:

await __event_emitter__(
    {
        "type": "files",
        "data": {"files": []}
    }
)

chat:title

更新当前聊天标题:

await __event_emitter__(
    {
        "type": "chat:title",
        "data": {"title": "Market Analysis Bot Session"}
    }
)

notification

显示前端 toast:

await __event_emitter__(
    {
        "type": "notification",
        "data": {"type": "success", "content": "Upload completed"}
    }
)

confirmation

请求用户确认:

confirmed = await __event_call__(
    {
        "type": "confirmation",
        "data": {
            "title": "Delete file?",
            "message": "This action cannot be undone."
        }
    }
)

input

请求用户输入:

value = await __event_call__(
    {
        "type": "input",
        "data": {
            "title": "Enter API Key",
            "message": "Paste your key below",
            "placeholder": "sk-..."
        }
    }
)

execute

在用户浏览器端执行 JavaScript:

result = await __event_call__(
    {
        "type": "execute",
        "data": {
            "code": "return window.location.href"
        }
    }
)

如果只想 fire-and-forget,也可以用 __event_emitter__

使用建议

  • 进度更新优先用 status
  • 需要用户确认或输入时,用 confirmation / input
  • 需要浏览器辅助能力时,用 execute
  • 需要兼容 Native 模式的 Tool / Function 时,避免把核心 UX 建立在会被 completion 快照覆盖的消息类事件上