跳转到主要内容

Remote Component 插件开发

本文说明如何开发一套新的 Assistant Workbench remote_component 类型插件。remote_component 是 View Extension 的一种视图 schema,不限定触发方式:它既可以作为普通 view slot 被宿主枚举展示,也可以由工具结果中的 xpert.extension_view 显式触发。该模式适合插件需要完整自定义 UI,而不是只使用声明式 table、list、stats、detail renderer 的场景。

架构

一套 remote component 插件至少由两部分组成;如果需要让 Agent 在对话中按需打开视图,再额外提供工具入口:
  1. ViewExtensionProvider:提供 manifest、data、parameter options、actions 和远程组件 HTML entry。
  2. 远程 React 页面:运行在 sandbox iframe 中,通过 postMessage 与宿主通信。
  3. 可选工具入口:返回 _meta['xpertai/visualization'],其中 typexpert.extension_view,用于工具触发型场景。
iframe 不是可信 API 调用方,因此不会拿到:
  • access token
  • API base URL
  • assistantId
  • hostId
  • hostType
  • 权限信息
请求链路是:
认证和授权发生在 data-xpert 与 xpert-pro:
  • data-xpert Web 通过 authenticatedFetch 携带当前用户 OIDC token。
  • data-xpert API 校验当前用户,并根据 assistantCode 解析 effective assistant。
  • data-xpert API 固定转发到 hostType=agenthostId=<assistant.assistantId>
  • xpert-pro 在调用 provider 前校验 view host 访问权限、manifest 可见性和 action 权限。

定义稳定 Key

先定义稳定 key。它们会成为 view host、Workbench canvas、可选工具结果和 provider 之间的公开协议。
公开 view key 的规则是:

选择视图触发方式

remote_component 可以通过两种方式进入宿主界面:
  • Slot 枚举型:宿主调用 GET /api/view-hosts/:hostType/:hostId/slots/:slot/views 获取某个 slot 下的 views,并按 manifest 渲染 remote component。
  • 工具触发型:工具调用结果携带 _meta['xpertai/visualization'],宿主只在对应工具被使用后打开这个视图。
如果你的插件视图是某个宿主页面的常驻扩展入口,优先使用 slot 枚举型。如果视图只应该随着某个工具调用结果出现,例如“打开指标管理”,再使用工具触发型。

可选:通过工具触发视图

工具只负责打开视图,不应该返回远程页面需要展示的完整数据。
不要在工具结果中放 hostIdhostType、API URL、token 或权限信息。真实宿主由 data-xpert 后端根据当前会话重新解析。

提供 Remote Component Manifest

通过 @ViewExtensionProvider(providerKey) 注册 provider,并在 agent.workbench.main slot 中返回 remote_component + react + iframe manifest。
如果变更类 action 需要比读取视图更高的权限,应在 action 上声明 permissions

返回 iframe HTML Entry

provider 需要为 iframe 返回单文件 HTML。推荐使用 @xpert-ai/plugin-sdkrenderRemoteReactIframeHtml(),让多个插件共享同一套 shell、reset、主题变量和 .xui-* UI 类。
entry 是 provider-local key,不是浏览器 URL。ViewExtension API 会拒绝绝对 URL、..、反斜杠等不安全值。

实现 Remote Bridge Client

iframe 页面通过 message 与父窗口通信,并用 requestId 关联响应。
Workbench 宿主只接受来自当前 iframe contentWindowinstanceId 匹配的消息。

示例:获取指标列表

远程页面不直接调用 fetch,而是请求宿主读取 view data:
宿主会转成:
data-xpert API 解析 assistant 后转发到 xpert-pro:
provider 处理查询:
结果会通过 message 回到 iframe:

示例:保存单个指标

新建和编辑可以复用同一个表单。远程页面提交受控 action:
宿主会转成:
provider 执行变更:
变更类 action 成功后应返回 refresh: true,这样宿主可以清理缓存,远程页面也可以刷新当前查询。

参数选项

下拉框和依赖字段使用 requestParameterOptions
provider 实现:

样式

remote component 应使用 renderRemoteReactIframeHtml() 提供的共享 .xui-* 类:
  • .xui-app
  • .xui-toolbar
  • .xui-control
  • .xui-input
  • .xui-button
  • .xui-button-primary
  • .xui-table
  • .xui-modal
  • .xui-notice
宿主会发送 init.theme.tokens,helper 会把它们映射为 --xui-* CSS variables。插件 CSS 应只补充业务布局,不要重新定义基础控件视觉。

构建 Assets

如果远程脚本放在插件源码目录下,需要确保包构建时复制到生产输出目录。

测试清单

上线前建议验证:
  • 工具返回合法 xpert.extension_view payload。
  • 公开 view key 符合 <providerKey>__<manifestKey>
  • manifest 返回 remote_component + react + iframe
  • getRemoteComponentEntry 返回 HTML,且不包含 token、API URL、assistantIdhostId
  • 列表加载通过 requestData
  • 保存通过 executeAction
  • 参数 options 支持独立字段和依赖字段。
  • 无权限用户无法访问 view host。
  • 必要时变更类 action 拥有比读取视图更严格的权限。
  • iframe 在 sandbox="allow-scripts" 且没有直接网络凭据的情况下可以正常工作。